﻿#include "EagleMainFrame.h"
#include <QSplitter>
#include <QDateTime>
#include <QDesktopWidget>
#include <QPushButton>
#include <QDialog>
#include <QLabel>
#include <QFormLayout>
#include <QMessageBox>
#include <future>
#include "EagleDeviceMgr.h"
#include <QDebug>
#include "QMetaType"
#include <QUuid>
#include "qevent.h"
#include "recordsetdlg.h"
#include "systemSetDlg.h"
#include "tipDlgs.h"
#include "qdisplaywidget.h"
#include <QtConcurrent>
#include <QScreen>
#include <sstream>
#include "camerasCtrl/camerasctrl.h"

#ifdef _WIN32
#include "../include/user_define/BoShiZhiDong.h"
#include "../include//user_define/CLSimulation.h"
#pragma comment(lib,"CamSerial.lib")
#pragma comment(lib,"CamerasCtrl.lib")
//#pragma comment(lib, "libboost_filesystem-vc120-mt-gd-1_55.lib")
#pragma comment(lib, "SDK.lib")
#pragma warning(disable : 4996)
#endif

static time_t last_cap_op_time = 0;

EagleMainFrame::EagleMainFrame(QWidget *parent)
	: QMainWindow(parent)
	, m_bFullScreen(false)
	, m_mainWidget(nullptr)
	, m_bRecPlay(false)
	, m_UiTask(this)
{
	ui.setupUi(this);
	
	qRegisterMetaType<TCbJob>("TCbJob");

	TDoubleAction dbAct;
	dbAct.m_icos << QIcon(":/res/image/Capture.png") << QIcon(":/res/image/stop_preview.png");
	dbAct.m_texts << ui.actionTPreview->text() << tr("停止");
	dbAct.m_tooltips << ui.actionTPreview->toolTip() << tr("停止预览");
	m_vDoubleIons.insert(E_INDEX_PREVIEW, dbAct);
	dbAct.clear();

	dbAct.m_icos << QIcon(":/res/image/camera.png") << QIcon(":/res/image/stop_record.png");
	dbAct.m_texts << ui.actionTRecord->text() << tr("停止");
	dbAct.m_tooltips << ui.actionTRecord->toolTip() << tr("停止记录");
	m_vDoubleIons.insert(E_INDEX_RECORD, dbAct);
	dbAct.clear();

	dbAct.m_icos << QIcon(":/res/image/1445087999_pauset.png") << QIcon(":/res/image/1445088015_start.png");
	dbAct.m_texts << ui.actionTPause->text() << tr("继续");
	dbAct.m_tooltips << ui.actionTPause->toolTip() << tr("继续记录");
	m_vDoubleIons.insert(E_INDEX_PAUSE, dbAct);
	dbAct.clear();

	dbAct.m_icos << QIcon(":/res/image/Bobine-video.png") << QIcon(":/res/image/replay_stop.png");
	dbAct.m_texts << ui.actionTRecPlay->text() << tr("停止");
	dbAct.m_tooltips << ui.actionTRecPlay->toolTip() << tr("停止回放");
	m_vDoubleIons.insert(E_INDEX_RECPLAY, dbAct);
	dbAct.clear();
	_timer = new QTimer(this);
	_timer->setInterval(2 * 1000);

	Init();

	QTimer::singleShot(5*1000,this, [this]()
	{
		_timer->start();
	});

	QThreadPool::globalInstance()->setMaxThreadCount(QDisPlayWidget::getIdealThreadCnt());
	
	QTimer::singleShot(10, this, [this]()    // 程序啟動后加載插件 连接设备
	{
		std::cout << "QThreadPool::globalInstance() maxThreadCnt:" << QThreadPool::globalInstance()->maxThreadCount()
			<< " IdealCnt:" << QThread::idealThreadCount() << std::endl;
		TimerPluginMgr::getInstance();
		DecoderPluginMgr::getInstance();
        OverlapPluginMgr::getInstance();
		QtConcurrent::run(this,&EagleMainFrame::ConnectWaitThread);
		//scanNetWork();   // 生成网卡 菜单
		ui.menu_net->menuAction()->setVisible(false);
		ui.menu_mount->menuAction()->setVisible(false);
	});

	connect(_timer, &QTimer::timeout, this, &EagleMainFrame::on_timeToFreshStat);
	this->setWindowTitle(GetMessageBoxTitle());
}

void EagleMainFrame::Init_UI()
{
	// 快导
	QActionGroup* group = new QActionGroup(this);
	group->addAction(ui.actionAoe);
	group->addAction(ui.actionQuickExport);
	EagleConfigFile::getInstance()->disk_mount_type.toInt() == 2 ? 
		ui.actionAoe->setChecked(true) : ui.actionQuickExport->setChecked(true);
	connect(group, &QActionGroup::triggered, this, [this](QAction* cur)
	{
		EagleConfigFile::getInstance()->save("_DiskMountType", cur == ui.actionAoe ? "2" : "4");
	});


	// 工具栏的2个列表框 [11/7/2016 ejitec]
	_toolcmb_dataNum = new QComboBox(this);
	_toolcmb_dataNum->addItems(QString("0,10,20,30,60,120,180,240,300,600,900,1200,1800").split(","));
	_toolcmb_dataNum->setEditable(true);
	_toolcmb_dataUnit = new QComboBox(this);
	_toolcmb_dataUnit->addItems(QString(tr("秒|帧数")).split("|"));

	ui.mainToolBar->insertWidget(ui.actionTPause,_toolcmb_dataNum);  
	ui.mainToolBar->insertWidget(ui.actionTPause, _toolcmb_dataUnit);
	ui.mainToolBar->setMovable(false);  //主菜单不可拖动
	ui.actionTPause->setEnabled(false);
	ui.treeWidget_dev->installEventFilter(ui.splitter);
	ui.treeWidget_dev->heardInit();
	ui.treeWidget_rec->installEventFilter(ui.splitter);
	ui.treeWidget_rec->heardInit();
	// 十字丝设置 [12/5/2017 xystar]
	QMenu* crossMenu = menuBar()->addMenu(tr("十字丝"));
	crossMenu->addAction(tr("设置"), this, [this]()
	{
		crossWireSetDlg dlg(this);
		dlg.exec();
	});

	// 增加仿真菜单栏 [11/23/2017 xystar]
	QMenu* simula = menuBar()->addMenu(tr("仿真播放"));
	simula->addAction(tr("相机播放"), this, &EagleMainFrame::on_SimuMenuPaly, QKeySequence(tr("alt+o", "仿真播放")));
	simula->addAction(tr("数据导入"), this, &EagleMainFrame::on_SimuMenuDataImport, QKeySequence(tr("alt+i", "数据导入")));

	// 创建居中
	QScreen* mainScreen = QGuiApplication::primaryScreen();
	this->resize(mainScreen->availableSize() * 3 / 5);
	QRect curRec = this->geometry();
	curRec.moveCenter(mainScreen->availableGeometry().center());
	this->setGeometry(curRec);  // 居中显示


#if 0

	QDesktopWidget* desktopWidget = QApplication::desktop();
	//得到客户区矩形
	//QRect clientRect = desktopWidget->availableGeometry();
	//得到应用程序矩形 宽度稍大
	QRect applicationRect = desktopWidget->screenGeometry();
	this->resize(QSize(applicationRect.size().width()*0.6, applicationRect.size().height()*0.75));

#endif
	
	//this->showMaximized();

	// 控件创建完毕后初始化大小
	ui.splitter->InitSplitter(this->width());
	ui.splitter->setMain(this);
	// 播放创建布局 设置 [11/8/2016 ejitec]
	_smallWndScroll = new QScrollArea(ui.widget_View);
	_smallWndWidget = new QWidget();
	_hLayoutOut = new QHBoxLayout(ui.widget_View);  // 主要
	_hLayoutOut->setSpacing(0);
	_hLayoutOut->setContentsMargins(0, 0, 0, 0);
	_vLayoutSmallWnds = new QVBoxLayout(_smallWndWidget);
	_smallWndScroll->setWidget(_smallWndWidget);
	_smallWndScroll->setWidgetResizable(true);
	_smallWndScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
	_smallWndScroll->hide();

	this->setIconSize(QSize(32,32));
	// set sheet style
	setGloabWndStyle();
	this->setWindowIcon(QIcon(":/res/image/ccd.ico"));
	ui.tabWidget->setTabIcon(0,QIcon(":/res/image/ccdlist.ico"));
	ui.tabWidget->setTabIcon(1, QIcon(":/res/image/explist.ico")); 
}

bool EagleMainFrame::Init()
{
	bool bRet = true;

	// 配置加载
	EagleConfigFile::getInstance()->load();

	Init_UI();

#ifdef WITH_FFMPEG
	// ffmpeg init
	av_register_all();
#endif

	int major = 0, minor = 0;
	EagleData_GetVersion(&major, &minor);
	qDebug() << QString("SDK Version: %1.%2").arg(major).arg(minor);
	//////////////////////////////////////////////////////////////////////////
	// 菜单栏所有信号 [11/28/2016 ejitec]
	
	// 1 系统
	connect(ui.actionMFormat, &QAction::triggered, this, &EagleMainFrame::on_SysMenuFormatDisk);
	connect(ui.actionMResetDefault, &QAction::triggered, this, &EagleMainFrame::on_SysMenutoFactory);
	connect(ui.actionMQuit, &QAction::triggered, this, [this]()
	{
		this->close();
	});

	// 2 采集
	connect(ui.actionMStartPreview, &QAction::triggered, ui.actionTPreview, &QAction::triggered);
	connect(ui.actionMStartRecord, &QAction::triggered, ui.actionTRecord, &QAction::triggered);
	connect(ui.actionMPauseRecord, &QAction::triggered, ui.actionTPause, &QAction::triggered);

	//3 数据列菜单 Menu [12/1/2016 ejitec]
	connect(ui.actionMGetRecordList, &QAction::triggered, this, &EagleMainFrame::on_DataMenuRescanRecList);
	connect(ui.actionMRename, &QAction::triggered, this, &EagleMainFrame::on_DataMenuRename);
	
	//4 自检 [12/1/2016 ejitec]
	connect(ui.actionMCheckData, &QAction::triggered, this, &EagleMainFrame::on_CheckData);
	connect(ui.actionMStartCheckSelf, &QAction::triggered, this, &EagleMainFrame::on_CheckRecord);
	
	//5 视图
	connect(ui.action_view_play, &QAction::triggered, ui.splitter, &MySplitter::on_viewDisplay);
	connect(ui.action_view_Normal, &QAction::triggered, ui.splitter, &MySplitter::on_viewNormal);
	connect(ui.action_view_ccdList, &QAction::triggered, ui.splitter, &MySplitter::on_viewCCDList);
	connect(ui.splitter, &MySplitter::evt_showCCD, this, [this]()
	{
		ui.tabWidget->setCurrentIndex(0);  // 设备
	});
	connect(ui.action_view_recList, &QAction::triggered, ui.splitter, &MySplitter::on_viewRECList);
	connect(ui.splitter, &MySplitter::evt_showRec, this, [this]()
	{
		ui.tabWidget->setCurrentIndex(1);  // 记录
	});

	//6 相机参数设置
	connect(ui.actionMSetCameraParm, &QAction::triggered, this, [this]()
	{

#if 1
		static camerasCtrl* dlg = nullptr;  // 避免开启多个窗口
		if (!dlg)
		{
			dlg = new camerasCtrl(this);
			dlg->setWindowModality(Qt::NonModal);
			dlg->setWindowFlags(dlg->windowFlags() | Qt::WindowMinimizeButtonHint);
			dlg->show();
			return;
		}
		if (dlg->isMinimized())
		{
			dlg->showNormal();
		}
		dlg->show();
#endif
		
	});

	// 系统设置 page 页面
	connect(ui.actionTSystemset, &QAction::triggered,this, [this]()
	{
		systemSetDlg* dlg = new systemSetDlg(this);
		dlg->exec();
		delete dlg;
		dlg = NULL;
	});

	connect(this, &EagleMainFrame::evt_netWorkChange, this, &EagleMainFrame::on_netWorkChange);
	// 工具栏操作 ToolBar [11/15/2016 ejitec]
	connect(ui.actionMSysInfo, &QAction::triggered, this, &EagleMainFrame::on_TShowSysInfo);
	connect(ui.actionTRecPlay, &QAction::triggered, this, &EagleMainFrame::on_TRecPlay);
	connect(ui.actionTExport, &QAction::triggered, this, &EagleMainFrame::on_TExport);
	connect(ui.actionTPreview, &QAction::triggered, this, &EagleMainFrame::on_TPreview);
	connect(ui.actionTRecord, &QAction::triggered, this, &EagleMainFrame::on_TRecord);
	connect(ui.actionTDel, &QAction::triggered, this, &EagleMainFrame::on_TDel);
	connect(ui.actionTPause, &QAction::triggered, this, &EagleMainFrame::on_TPauseRec);

	// 链接 记录列表右键 contextMenu
	connect(ui.treeWidget_rec, &recListWidgets::evt_ActRecReplay,ui.actionTRecPlay,&QAction::triggered);
	connect(ui.treeWidget_rec, &recListWidgets::evt_ActRecExport, ui.actionTExport, &QAction::triggered);
	connect(ui.treeWidget_rec, &recListWidgets::evt_ActRecRenam, ui.actionMRename, &QAction::triggered);
	connect(ui.treeWidget_rec, &recListWidgets::evt_ActRecDel, ui.actionTDel, &QAction::triggered);

	//
	connect(this, &EagleMainFrame::evt_rawLog, ui.statusBar, &customStatusBar::on_FetchMsg);
	// 工作线程 用于 异步操作
	m_ptJobHander = new EvtThreadHandler(this, [=](TCbJob tcb){  // 定义一个传出函数
		this->on_WorkFinish(tcb);
	});

	connect(this, &EagleMainFrame::evt_workFinish, this, &EagleMainFrame::on_WorkFinish);
		
	bRet = (EagleData_Init() == 0);


#ifdef _NODEVICE

	QTimer::singleShot(1000, this, [this]()
	{
		TDevWithCCDInfo* ptDevInfo = new TDevWithCCDInfo();
		ptDevInfo->m_diskMap = { 'A' };
		ptDevInfo->m_fTemp = 100;
		ptDevInfo->m_strDevNam = "Demo";
		ptDevInfo->m_nDevID = 168;
		ptDevInfo->m_vCCDInfo.resize(10);
		int i = 0;
		for (auto& it : ptDevInfo->m_vCCDInfo)
		{
			++i;
			it.m_bValid = true;
			it.m_strCCDNam = "userCCD" + QString::number(i);
			it.m_tInfo.camera_no = i;
			it.m_tInfo.color_depth = 16;
			it.m_tInfo.column = 1024;
			it.m_tInfo.line = 1024;
		}
		m_vDevList.push_back(ptDevInfo);

		createPlayWnds();
	});
	
#endif
	connect(this, &EagleMainFrame::evt_recListChange, this, [this]()
	{
		TCbJob tJob;
		tJob.m_eType = E_JOBTYPE_FETCHRECORDLIST; 
		m_ptJobHander->postJob([this]()  // 线程任务 
		{
			if (m_recTreeLock.try_lock())
			{
				fetchRecList();
				m_recTreeLock.unlock();
			}

			return true;
			
		}, tJob);
	});

	// 通知录像列表变更 [11/18/2016 ejitec]
	EagleData_RegisterRecListChangeCallback([]()
	{
		qDebug() << "EagleData_RegisterRecListChangeCallback() cbT called!!";
		//emit g_theApp->evt_recListChange();
	});

	record_status = EagleControlStart;
	replay_status = EagleControlStart;
	record_type = RECORD_SECOND;
	record_suspend_status = EagleControlStart;
	cap_status_expected = ECaptureReady;
	
	
	return bRet;
}

EagleMainFrame::~EagleMainFrame()
{
	qDebug() << "EagleSdkDemo quiting ...";

	try
	{
		destoryPlayWnds();
		delete m_ptJobHander;
		m_ptJobHander = NULL;
		ui.treeWidget_rec->clear();
		ui.treeWidget_dev->clear();

		// 线程类任务 清除工作 [11/1/2016 ejitec]
		CEagleDeviceMgr::GetInstance()->CloseFetchThread();
		CEagleDeviceMgr::GetInstance()->ClearDevices();
	}
	catch (...)
	{
		qDebug() << "EagleSdkDemo quitting error catched ...";
	}
	
	qDebug() << "EagleSdkDemo quitted ...";
}

void EagleMainFrame::scanNetWork()   //
{
	eagle_all_netcards tNics;  //
	memset(&tNics, 0, sizeof(tNics));
	int ret = EagleControl_GetSystemNICs(&tNics);
	qDebug() << QString("").sprintf("%d system netcards:\n", tNics.card_num);
	QActionGroup* aG = new QActionGroup(this);

	for (int i = 1; i <= tNics.card_num; i++) 
	{
		QAction* menu1 = new QAction(this);
		menu1->setText(tNics.cards[i - 1].dev_description);
		menu1->setCheckable(true);
		aG->addAction(menu1);
		if (i == 1)
		{
			menu1->setChecked(true);
		}
		// 保存数据用于 接收方 响应
		QVariant var;
		var.setValue(tNics.cards[i - 1]);
		menu1->setData(var);
		ui.menu_net->addAction(menu1);
		qDebug() << QString("").sprintf("%d : %s\n", i, tNics.cards[i - 1].dev_description);
		connect(menu1, &QAction::triggered, this, &EagleMainFrame::on_setControlNICs);
	}
	QAction* menuTest = new QAction(tr("测试额外对话框"),this);
	ui.menu_net->addAction(menuTest);

	connect(menuTest, &QAction::triggered, this, [this]()
	{
		static QDisPlayWidget* testWnd = new QDisPlayWidget(this);
		extraParamsDlg dlg(testWnd);
		dlg.exec();
	});
}

void EagleMainFrame::on_setControlNICs()
{
	// 重新布局
	destoryPlayWnds();
	ui.treeWidget_dev->clear();  // 
	ui.treeWidget_rec->clear();

	QAction* pAction = qobject_cast<QAction*>(sender());
	eagle_netcard_info info = pAction->data().value<eagle_netcard_info>();
	// 设置查询列表
	eagle_all_netcards set_nics = { 0 };
	// 响应一个菜单只响应一个 按钮
	memcpy(&set_nics.cards[set_nics.card_num++], &info, sizeof(eagle_netcard_info));

	qDebug() << "on_setControlNICs() 2" << QThread::currentThreadId();
	int ret = EagleControl_SetControlNICs(&set_nics);
	if (ret)
	{
		qDebug() << "EagleControl_SetControlNICs error!";
		return;
	}

	// 
	TCbJob tJob;
	tJob.m_eType = E_JOBTYPE_SCANNDEVLIST;
	m_ptJobHander->postJob([this]()
	{
		return CEagleDeviceMgr::GetInstance()->RescanDevices();
		//	fetchDevList();
	}, tJob);

	tJob.m_eType = E_JOBTYPE_FETCHRECORDLIST;
	m_ptJobHander->postJob([this]()
	{
		fetchRecList();

		return true;

	}, tJob);
}

void EagleMainFrame::fetchDevList()
{
	m_vDevList.clear();
	/*
	* get device number
	*/
	int device_num = 0;
	int ret = EagleControl_ScanAndGetDeviceNum(&device_num);
	qDebug() << QString("").sprintf("EagleControl_ScanAndGetDeviceNum:%s get device numbers %d", ret == 0 ? "success" : "failed"
		, device_num);

	/*
	* get device ids
	*/
	int *device_ids = new int[device_num];  // 考虑装入列表
	int ids = 0;
	ret = EagleControl_GetDeviceIds(device_ids, device_num, &ids);
	if (device_num == 0)
	{
		return;
	}
	qDebug() << ("Got device ids as follow:");
	for (int i = 0; i < ids; i++)
	{
		TDevWithCCDInfo* ptDevInfo = new TDevWithCCDInfo();
		wchar_t serial[32] = { '\0' };
		
		int device_id = device_ids[i];
		ret = EagleControl_GetSystemStatus(device_id, &ptDevInfo->m_tStatus);
		ret = EagleControl_GetCameraDiskMapping(device_id, &ptDevInfo->m_diskMap);
		EDeviceType device_type = EagleControl_GetDeviceType(ids);

		EagleControl_GetDeviceName(device_id, serial);
		ptDevInfo->m_nDevID = device_id;
		ptDevInfo->m_strDevNam = QString::fromWCharArray(serial);
		ptDevInfo->m_device_type = device_type;

		qDebug() << QString("").sprintf(" ** %d: device id %d,", i + 1, device_ids[i])
			+ QString("EDeviceType:%1,device_id:%3,DevNam:%2")
			.arg(int(device_type)).arg(ptDevInfo->m_strDevNam).arg(device_id);

		int camera_num = 0;
		int ret = EagleControl_GetMaxCameraNumber(device_id, &camera_num);
		for (int cam_index = 0; cam_index < camera_num; cam_index++)
		{
			TCCDInfo tCCDInfo;
			wchar_t ccd_name[32] = { '\0' };
			if (!EagleControl_IsCameraValid(device_id, cam_index + 1))
			{
				tCCDInfo.m_bValid = false;
			}

			tCCDInfo.m_tInfo.camera_no = cam_index + 1;
			ret = EagleControl_GetCameraCaptureParam(device_id, &tCCDInfo.m_tInfo);
			EagleControl_GetCameraName(device_id, cam_index + 1, ccd_name);
			tCCDInfo.m_strCCDNam = QString::fromWCharArray(ccd_name);
			qDebug() << QString("DevNam:%1,ccd_name:%2").arg(ptDevInfo->m_strDevNam, tCCDInfo.m_strCCDNam);

			ptDevInfo->m_vCCDInfo.push_back(tCCDInfo);
		}

		m_vDevList.push_back(ptDevInfo);
	}
}

void EagleMainFrame::fetchRecList()
{
	qDeleteAll(m_vRecList);
	m_vRecList.clear();

	int nRecordNumer = EagleData_GetRecordNumber();
	if (nRecordNumer == 0)
	{

#if 0  // forTest

		EagleData_Record_Id rec;
		m_vRecList.clear();
		wcscpy(rec.task_name, L"chk");
		rec.start_time = 1474197857;
		m_vRecList.push_back(rec);
		rec.start_time = 1474193665;
		m_vRecList.push_back(rec);
		rec.start_time = 1474193657;
		m_vRecList.push_back(rec);
		wcscpy(rec.task_name, L"test");
		rec.start_time = 1474191100;
		m_vRecList.push_back(rec);
		rec.start_time = 1474191200;
		m_vRecList.push_back(rec);
		wcscpy(rec.task_name, L"chk");
		rec.start_time = 1474191300;
		m_vRecList.push_back(rec);

#endif
		return;
	}
	
	EagleData_Record_Id* record_info = new EagleData_Record_Id[nRecordNumer];
	memset(record_info, 0, sizeof(EagleData_Record_Id)* nRecordNumer);
	int nRealNum = EagleData_GetRecordList(record_info, nRecordNumer);
	
	for (int i = 0; i < min(nRealNum, nRecordNumer);i++) // 清空多余的内存空间
	{
		m_vRecList << new EagleData_Record_Id(record_info[i]);
	}

	delete[] record_info;
}

void EagleMainFrame::on_WorkFinish(TCbJob tCb)
{
	qDebug() << "on_WorkFinish finished type:" << (int)(tCb.m_eType)
		<< ",ThreadID:" << QThread::currentThreadId();

	switch (tCb.m_eType)
	{
	case E_JOBTYPE_NORMAL:
	{
		break;
	}
	case E_JOBTYPE_SCANNDEVLIST:
	{
		setDevTree();
		createPlayWnds();
// 		int nWidth = size().width();
// 		//ui.tabWidget->tabBar()->setElideMode(Qt::ElideNone);
// 		qDebug() << ui.tabWidget->tabBar()->width() << "," << nWidth / 5;
// 		//ui.splitter->setSizes(ui.tabWidget->tabBar()->width());
// 		//ui.splitter->setSizes(QList<int>() << 200 << nWidth);

		break;
	}
	case E_JOBTYPE_FETCHRECORDLIST:
	{
		setRecTree();
		break;
	}
	default:
		break;
	}
}

void EagleMainFrame::UpdateAllTools(ECaptureStatusType current_status, bool need_delay)
{
	bool bUsable = current_status == ECaptureReady && replay_status == 0;
	bool displalying = IsDisplayPanelInDisplaying(need_delay);
	
	ui.actionTSystemset->setEnabled(bUsable);
	// 工具栏 导出 回放 删除
	ui.actionTExport->setEnabled(bUsable);
	ui.actionTDel->setEnabled(bUsable);

	ui.actionTPreview->setEnabled(replay_status == 0);
	ui.actionTRecord->setEnabled(replay_status == 0);
	ui.actionTPause->setEnabled((current_status >= ECaptureRecording && record_type == RECORD_SECOND)
		|| (current_status == ECapturePaused && record_type == RECORD_FNM));
	ui.actionTRecPlay->setEnabled(displalying == false && record_status == 0 || replay_status != EagleControlStart);

	// systemMenu
	ui.actionMSysInfo->setEnabled(bUsable);
	
	// 数据菜单
	ui.actionMRename->setEnabled(bUsable);
	// 自检菜单
	ui.actionMCheckData->setEnabled(bUsable);
	ui.actionMStartCheckSelf->setEnabled(bUsable);

	// captureMenu  此处菜单需要动态设置文字
	ui.actionMStartPreview->setEnabled(replay_status == 0);
	ui.actionMStartRecord->setEnabled(replay_status == 0);
	ui.actionMPauseRecord->setEnabled(current_status >= ECaptureRecording);

	// 以下四个按钮 更换图标
// 	ui.actionTPreview->setIcon(displalying == false || (displalying  && replay_status == EagleControlContinue)
// 		? g_icon_startPreview : g_icon_stopPreview);
	TDoubleAction* it = &(m_vDoubleIons[E_INDEX_PREVIEW]);
	// 在没有播放 或者  录像回放下 时 预览显示正常图标
	bool bPrev = (current_status == ECaptureTasking) || (displalying  && current_status > ECaptureTasking);
		//ui.actionTPreview->setIcon(it->icon(displalying == false || (displalying  && replay_status == EagleControlContinue)));
	ui.actionTPreview->setIcon(it->icon(!bPrev));
	ui.actionTPreview->setText(it->text());
	ui.actionTPreview->setToolTip(it->toolTip());
	ui.actionMStartPreview->setText(it->toolTip());
	//bool bvalid = current_status > ECaptureReady && displalying == false || record_status == EagleControlContinue;
	bool bNormal = (current_status <= ECaptureTasking) || (record_status == EagleControlStart);
	it = &(m_vDoubleIons[E_INDEX_RECORD]);
	ui.actionTRecord->setIcon(it->icon(bNormal));
	ui.actionTRecord->setText(it->text());
	ui.actionTRecord->setToolTip(it->toolTip());
	ui.actionMStartRecord->setText(it->toolTip());
// 	ui.actionTPause->setIcon(record_suspend_status == EagleControlStart
// 		? g_icon_startPause : g_icon_stopPause);
	
	it = &(m_vDoubleIons[E_INDEX_PAUSE]);
	ui.actionTPause->setIcon(it->icon(record_suspend_status == EagleControlStart));
	ui.actionTPause->setText(it->text());
	ui.actionTPause->setToolTip(it->toolTip());
	ui.actionMPauseRecord->setText(it->toolTip());
//	ui.actionTRecPlay->setIcon(replay_status == EagleControlStart ? g_icon_startRecplay : g_icon_stopRecplay);
	it = &(m_vDoubleIons[E_INDEX_RECPLAY]);
	ui.actionTRecPlay->setIcon(it->icon(replay_status == EagleControlStart));
	ui.actionTRecPlay->setText(it->text());
	ui.actionTRecPlay->setToolTip(it->toolTip());
}

void EagleMainFrame::on_timeToFreshStat()
{
	static unsigned long long timer_count = 0;

	ECaptureStatusType cur_sys_status = GetCurrentSystemStatus(false);
	
	//qDebug() << QString("").sprintf("except %d, real %d", cap_status_expected, cur_sys_status);
	if ((cur_sys_status != cap_status_expected && time(NULL) - last_cap_op_time > 5) || timer_count == 0)
	{
		if (cur_sys_status == ECaptureReady) // the state after power up and stop task + devOffLine
		{
			if (cap_status_expected == ECaptureTasking)
			{
				//Logger(EInfo, EagleLog_I_Device_Separatly_Stop_Task);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Stop_Task);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Stop_Task));
			}
			else if (cap_status_expected == ECaptureRecording   // 同步暂停状态
				|| cap_status_expected == ECapturePaused)
			{
				//Logger(EInfo, EagleLog_I_Device_Separatly_Stop_Record);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record));
				record_status = record_suspend_status = EagleControlStart;
			}
			if (IsDisplayPanelInDisplaying(false) && timer_count != 0)
			{
				StopDisplayModule();
				std::this_thread::sleep_for(std::chrono::milliseconds(200));
			}
		}
		else if (cur_sys_status == ECaptureTasking)
		{
			if (cap_status_expected == ECaptureReady)
			{
				//Logger(EInfo, EagleLog_I_Device_Separatly_Start_Task);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Start_Task);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Start_Task));
			}
			else if (cap_status_expected == ECaptureRecording)
			{
				record_status = record_suspend_status = EagleControlStart;
				//Logger(EInfo, EagleLog_I_Device_Separatly_Stop_Record);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record));
			}
			else if (cap_status_expected == ECapturePaused)
			{
				record_status = record_suspend_status = EagleControlStart;
				//Logger(EInfo, EagleLog_I_Device_Separatly_Stop_Record);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Stop_Record));
			}
			if (IsDisplayPanelInDisplaying(false) == false)
			{
				std::async(std::launch::async,&EagleMainFrame::StartDisplayModuleThread, this);
			}
		}
		else if (cur_sys_status == ECaptureRecording)
		{
			if (cap_status_expected == ECapturePaused)
			{
				record_suspend_status = EagleControlStart;
				//Logger(EInfo, EagleLog_I_Device_Separatly_Resume_Record);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Resume_Record);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Resume_Record));
			}
			else if (cap_status_expected == ECaptureReady  // 断网恢复
				|| cap_status_expected == ECaptureTasking)  //  串口操作
			{
				record_status = EagleControlContinue;
				record_suspend_status = EagleControlStart;
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Start_Record));

				if (cap_status_expected == ECaptureReady)  // 断网下 重连强制打开预览 [6/22/2017 xystar]
				{
					if (IsDisplayPanelInDisplaying(false) == false)
					{
						std::async(std::launch::async, &EagleMainFrame::StartDisplayModuleThread, this);
					}
				}
			}
			else
			{
				record_suspend_status = EagleControlContinue;
				//Logger(EInfo, EagleLog_I_Device_Separatly_Start_Record);
				//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Start_Record);
				emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Start_Record));
			}
		}
		else if (cur_sys_status == ECapturePaused)
		{
			//Logger(EInfo, EagleLog_I_Device_Separatly_Pause_Record);
			//qInfo() << GetLogFormat(EagleLog_I_Device_Separatly_Pause_Record);
			emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Device_Separatly_Pause_Record));
			record_status = record_suspend_status = EagleControlContinue;
		}

		cap_status_expected = cur_sys_status;
		UpdateAllTools(cur_sys_status, false);
	}
	timer_count += 1;

}

void EagleMainFrame::StopDisplayModule()
{
	//有时候DisplayModule的状态会和预期的不一致，比如：设备采集过程中/导出过程中...异常断电后再上电，
	//而软件没有退出，重新连接上之后DisplayModule的状态还是在Display或其他状态，而这个时候需要让
	//DisplayModule归位后才能进行其他操作，否则后果...
	//重要：never do it in main thread
	for (auto it = m_CurPlayWnds.begin(); it != m_CurPlayWnds.end(); it++)
	{
		qApp->postEvent(*it,new MessageCmd(GT_CMD_REALTIME_STOP_PLAY));
	}
	m_CurPlayWnds.clear();
}

void EagleMainFrame::StartDisplayModuleThread()
{
	eagle_capture_config config;
	for (auto dev_it = m_DisplayWnds.begin(); dev_it != m_DisplayWnds.end(); dev_it++)
	{
		config.camera_no = (*dev_it)->CCDID();
		EagleControl_GetCameraCaptureParam((*dev_it)->DevID(), &config);
		if (config.capture_status > ECaptureReady)
		{
			MessageCmd* ptcmd = new MessageCmd(GT_CMD_REALTIME_START_PLAY);
			MessageCmd& cmd = *ptcmd;
			cmd.device_id = (*dev_it)->DevID();
			cmd.ccd_serial = config.camera_no;
			cmd.column = config.column;
			cmd.line = config.line;
			cmd.frame_rate = config.frame_rate;
			cmd.color_depth = config.color_depth;
			cmd.sampling_format = CEagleDeviceMgr::GetInstance()->GetSdiMode((*dev_it)->DevID());
			qApp->postEvent(*dev_it, ptcmd);
			m_CurPlayWnds.push_back(*dev_it);
		}
	}
	//QThread::msleep(500);
	ECaptureStatusType cur_sys_status = GetCurrentSystemStatus(false);
	doWorkInUi_2([this, cur_sys_status]()
	{
		QTimer::singleShot(200, [this, cur_sys_status]()
		{
			UpdateAllTools(cur_sys_status,false);
		});
	});
}

void EagleMainFrame::reLayOutWnds(QWidget* Wnd)
{
	QDisPlayWidget* DisWnd = qobject_cast<QDisPlayWidget*>(Wnd);
	BaseDisParentWnd* curWnd = DisWnd->getParent();

	_hLayoutOut->removeWidget(_smallWndScroll);
	// 窗口对调  返回 curWnd的布局 curWnd自己管理 [10/22/2016 ejitec]
	_vLayoutSmallWnds->replaceWidget(curWnd, m_mainWidget->getParent());
	_hLayoutOut->addWidget(curWnd,4);
	_hLayoutOut->addWidget(_smallWndScroll,1);
	
	if (m_mainWidget)
	{
		m_mainWidget->InCenter(false);
	}
	m_mainWidget = DisWnd;
	m_mainWidget->InCenter(true);

}

void EagleMainFrame::createPlayWnds()
{
	_smallWndScroll->hide();

	int i = 0;

	for(auto dev : m_vDevList)
	{
		for (auto& ccd : dev->m_vCCDInfo)
		{
			if (!ccd.m_bValid)
			{
				continue;
			}
			BaseDisParentWnd* Basewnd = new BaseDisParentWnd(ui.widget_View, ccd,dev->m_strDevNam,QString("%1_%2_%3")
				.arg(dev->m_strDevNam).arg(ccd.m_strCCDNam).arg(i + 1));
			QDisPlayWidget* wnd = Basewnd->DisPlayWnd();
			connect(wnd, &QDisPlayWidget::evt_stopRec, this, &EagleMainFrame::on_TRecPlay);
			wnd->installEventFilter(ui.splitter);
			wnd->DevID(dev->m_nDevID);
			wnd->CCDID(ccd.m_tInfo.camera_no);
			m_DisplayWnds << wnd;
			m_BaseDisWnds << Basewnd;

#ifdef  XIANGS_VERSION
			// 加载附加参数
			wnd->setExpParams(EagleConfigFile::getInstance()->GetDeviceCameraExtraParam(dev->m_nDevID, ccd.m_tInfo.camera_no));
#endif
			if (i == 0)
			{
				m_mainWidget = wnd;
				m_mainWidget->InCenter(true);
				_hLayoutOut->addWidget(Basewnd,4);   // 中央窗口最大化 [11/14/2016 ejitec]
			}
			else
			{
				wnd->InCenter(false);
				_vLayoutSmallWnds->addWidget(Basewnd);
			}

			i++;
		}
	}

	if (_vLayoutSmallWnds->count() != 0)
	{
		_vLayoutSmallWnds->addStretch(/*4 - _vLayoutSmallWnds->count()*/1);
		_smallWndScroll->show();
		// 必须设置
		_hLayoutOut->addWidget(_smallWndScroll,1);	// 外层对 scroll操作 不对内部widget操作 
		//_hLayoutOut->setStretch(0, 1); 
	}
}

void EagleMainFrame::destoryPlayWnds()
{
	if (m_BaseDisWnds.size() <= 1 && m_mainWidget)
	{
		_hLayoutOut->removeWidget(m_BaseDisWnds[0]);
//		m_BaseDisWnds.pop_front();
// 		delete m_BaseDisWnds[0];
// 		m_BaseDisWnds[0] = NULL;
	}
	else
	{
		for (auto it : m_BaseDisWnds)
		{
			_vLayoutSmallWnds->removeWidget(it);
// 			delete it;
// 			it = NULL;
		}
	}
	
	QLayoutItem* child = nullptr;  // 删除所有的 strech
	while ((child = _vLayoutSmallWnds->takeAt(0)) != 0) 
	{
		delete child;
		child = nullptr;
	}
	m_mainWidget = nullptr;
	//m_BaseDisWnds.clear();
	qDeleteAll(m_BaseDisWnds);
	m_BaseDisWnds.clear();
	m_DisplayWnds.clear();
	m_CurPlayWnds.clear();
}

QDisPlayWidget* EagleMainFrame::getPlayWndBy(int devID, int ccdID)
{
	for (auto it : m_DisplayWnds)
	{
		if (it->CCDID() == ccdID && it->DevID() == devID)
		{
			return it;
		}
	}

	return nullptr;
}

void EagleMainFrame::postMessageBy(int devID, int ccdID, MessageCmd* ptCmd)
{
	QDisPlayWidget*ptWnd = getPlayWndBy(devID, ccdID);

	if (ptWnd)
	{
		ptWnd->PostEvent(ptCmd);
	}
}

void EagleMainFrame::setDevTree()
{
	QTreeWidgetItem* head = ui.treeWidget_dev->headerItem();
	ui.treeWidget_dev->clear();

	if (m_vDevList.size() == 0)
	{
		return;
	}

	m_nCameraCnt = 0;
	QVariant var;
	ui.treeWidget_dev->disConnectCheck();
	for (auto dev : m_vDevList)
	{
		qDebug() << "ui.treeWidget_dev B:" << ui.treeWidget_dev->columnCount();
		QTreeWidgetItem* hearditem = new QTreeWidgetItem(ui.treeWidget_dev
			, QStringList() << dev->m_strDevNam,ITEM_PARENT);
		qDebug() << "ui.treeWidget_dev E:" << ui.treeWidget_dev->columnCount();
		baseCCDItemData* device_data = new DeviceClientData(dev->m_nDevID, dev->m_device_type);
		var = QVariant::fromValue(device_data);
		hearditem->setData(0, Qt::UserRole,var);
		hearditem->setCheckState(0, CEagleDeviceMgr::GetInstance()->IsDeviceChecked(dev->m_nDevID) ? Qt::Checked : Qt::Unchecked);

		for(TCCDInfo ccd : dev->m_vCCDInfo)
		{
			if (!ccd.m_bValid)
			{
				continue;
			}

			QTreeWidgetItem* childItem = new QTreeWidgetItem(hearditem, QStringList() << ccd.m_strCCDNam,ITEM_CHILD);
			baseCCDItemData* ccd_data = new CcdClientData(dev->m_nDevID, ccd.m_tInfo.camera_no, dev->m_device_type);
			var = QVariant::fromValue(ccd_data);
			childItem->setData(0, Qt::UserRole, var);
			childItem->setCheckState(0,EagleControl_IsCameraChecked(dev->m_nDevID, ccd.m_tInfo.camera_no) ? Qt::Checked : Qt::Unchecked);
			hearditem->addChild(childItem);
			
			m_nCameraCnt++;
		}
	}
	
	ui.treeWidget_dev->expandAll();
	// 在完成树后监控 check状态 [11/17/2016 ejitec]
	ui.treeWidget_dev->setCheckConnection();
}

void EagleMainFrame::setRecTree()
{
	std::lock_guard<std::mutex> locker(m_recTreeLock);
	ui.treeWidget_rec->clearSelection();
	ui.treeWidget_rec->clear();
	ui.treeWidget_rec->setSelectionBehavior(QTreeWidget::SelectionBehavior::SelectItems);
	ui.treeWidget_rec->setSelectionMode(QTreeWidget::SelectionMode::ExtendedSelection);

	if (m_vRecList.size() == 0)
	{
		return;
	}

	QTreeWidgetItem* head = ui.treeWidget_rec->headerItem();
	QTreeWidgetItem* hearditem = NULL;
	for(auto rec : m_vRecList)
	{
		QList<QTreeWidgetItem*> itemList = ui.treeWidget_rec->findItems(QString::fromWCharArray(rec->task_name), Qt::MatchStartsWith);
		if (itemList.size() == 0)
		{
			hearditem = new QTreeWidgetItem(ui.treeWidget_rec,
			QStringList() << QString::fromWCharArray(rec->task_name),ITEM_PARENT);
			hearditem->sortChildren(0, Qt::AscendingOrder);
		}
		else
		{
			//qDebug() << "items size:" << itemList.size();rec
			hearditem = itemList[0];
		}

		QDateTime dt = QDateTime::fromTime_t(rec->start_time);
		QTreeWidgetItem* childItem = new QTreeWidgetItem(hearditem,
			QStringList() << QString::fromWCharArray(rec->task_name) + " - " + 
			dt.toString("yy/MM/dd hh:mm:ss"), ITEM_CHILD);
		childItem->setIcon(0, QIcon(":/res/image/record.png"));
		//ui.treeWidget_rec->setItemWidget(childItem,1,createItemWidget(ui.treeWidget_rec));
		QVariant data = QVariant::fromValue(rec);
		childItem->setData(0, Qt::UserRole, data);
	}

	qDebug() << "topLevelItemCount:" << ui.treeWidget_rec->topLevelItemCount();
	ui.treeWidget_rec->expandAll();
}

// 仅提供参考 实际使用 clear方法替代
void EagleMainFrame::clearTree(QTreeWidget* ptTree)
{
	//如果没有父节点就直接删除
	while(ptTree->topLevelItemCount() != 0)
	{
		QTreeWidgetItem* item = ptTree->takeTopLevelItem(0);
		{
			int nChild = item->childCount();
			for (int j = 0; j < nChild; j++)
			{
				delete item->child(j);
			}
		}

		delete item;
		item = NULL;
	}

	ptTree->clear();

	/************************************************************************/
	/* 
		// 从选中删除 
		QTreeWidgetItem * currentItem = ui->tv_Source->currentItem();

		if(currentItem==Q_NULLPTR)
		{
		return;
		}
		//如果没有父节点就直接删除
		if(currentItem->parent()==Q_NULLPTR)
		{
		delete ui->tv_Source->takeTopLevelItem(ui->tv_Source->currentIndex().row());
		}
		else
		{
		//如果有父节点就要用父节点的takeChild删除节点
		delete currentItem->parent()->takeChild(ui->tv_Source->currentIndex().row());
		}
	
	*/
	/************************************************************************/
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

void EagleMainFrame::closeEvent(QCloseEvent *event)
{
	if (cap_status_expected != ECaptureReady)
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Quit_Still_Running_Alarm));
		event->ignore();
		return;
	}

	QMessageBox box(QMessageBox::Warning,GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Quit_Alarm),
		QMessageBox::Ok | QMessageBox::Cancel,this);
// 	box.setWindowIcon(QIcon(":/res/image/ccd.ico"));
// 	box.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
	box.setButtonText(QMessageBox::Ok, tr("确定"));
	box.setButtonText(QMessageBox::Cancel, tr("取消"));

	if (box.exec() == QMessageBox::Ok)
	{
		event->accept();
	}
	else
	{
		event->ignore();
	}
}

bool EagleMainFrame::eventFilter(QObject *watched, QEvent *e)
{
	return QObject::eventFilter(watched, e);
}

void EagleMainFrame::on_TShowSysInfo()
{
	vector<int> devList;
	CEagleDeviceMgr::GetInstance()->GetAllDevice(devList);
	systemInfoDlg dlg(this, devList);

	dlg.exec();

// 	/************************************************************************/
// 	/* 
// 		"<p align=\"center\" color=\"red\">"
// 		 			"<span >%1"
// 				"</span></p>"
// 	*/
// 	/************************************************************************/
// 	QLabel* proLabel1 = new QLabel(&dlg);
// 	// label 字体上色 加粗 大小 对齐 富文本设置[10/18/2016 ejitec]
// 	proLabel1->setText(tr("<p align=\"left\" >"
// 		"<font color=\"red\" size=12><b>%1</b></font></p>").arg(tr("属性值1")));
// 	QPalette pa;
}

void EagleMainFrame::threadFun_remout(std::shared_ptr<EagleData_Record> spRecord)
{
	if (!spRecord)
	{
		return;
	}

	std::vector<int> device_id;
	EagleData_CcdRecord* ccd_record = spRecord->ccd_record_list;
	while (ccd_record != 0)
	{
		bool bAdded = false;
		for (auto it = device_id.begin(); it != device_id.end(); it++)
		{
			if (ccd_record->id.device_id == *it){
				bAdded = true;
				break;
			}
		}
		if (!bAdded)
			device_id.push_back(ccd_record->id.device_id);
		ccd_record = ccd_record->next;  // 一条录像有 多个CCD同时记录
	}

	remountByDevs(device_id);
	
	return;
}

void EagleMainFrame::remountBySelRecords()
{
	std::vector<void*> records = ui.treeWidget_rec->GetSelectedRecords();
	std::vector<int> device_id;
	for (auto it = records.begin(); it != records.end(); it++)
	{
		EagleData_Record_Id* record_id = (EagleData_Record_Id*)(*it);
		EagleData_Record *record = EagleDataMgr::GetInstance()->GetRecord(record_id);
		EagleData_CcdRecord* ccd_record = record->ccd_record_list;
		while (ccd_record != 0)
		{
			bool bAdded = false;
			for (auto it = device_id.begin(); it != device_id.end(); it++)
			{
				if (ccd_record->id.device_id == *it)
				{
					bAdded = true;
					break;
				}
			}
			if (!bAdded)
				device_id.push_back(ccd_record->id.device_id);
			ccd_record = ccd_record->next;
		}
	}

	remountByDevs(device_id);
}

void EagleMainFrame::remountByDevs(vector<int>& device_id)
{
	CursorWait wait(GetLogFormat(EagleLog_M_Mounting_Disk));

	std::vector<std::future<void>> checker;
	for (auto it = device_id.begin(); it != device_id.end(); it++)
	{
		checker.push_back(std::async(std::launch::async,[=]()
		{
			DISK_MOUNT_TYPE type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toInt();
			int ret = EagleData_CheckAndRemountFileSystem(*it, type);
			QThread::msleep(10 * 1);
			return;
		}));
	}

	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++)
		{
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1)))
			{
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::seconds(1));
		else
			break;
	}

	return;
}

//
void EagleMainFrame::on_TRecPlay()
{
	if (m_bRecPlay)  // 停止录像播放
	{
		if (sender() == ui.actionTRecPlay)  // 主界面调用
		{
			for (auto it : m_DisplayWnds)
			{
				if (m_CurPlayWnds.contains(it))
					qApp->postEvent(it, new MessageCmd(GT_CMD_REPLAY_STOP));
			}
			m_CurPlayWnds.clear();
		}
		else
		{
			for (auto it : m_CurPlayWnds)  //  播放窗口播放结束时  窗口 调用
			{
				if (it == sender())
				{
					m_CurPlayWnds.removeAt(m_CurPlayWnds.indexOf(it));
					qApp->postEvent(it, new MessageCmd(GT_CMD_REPLAY_STOP));
					
					break;
				}
			}
		}
		
		if (m_CurPlayWnds.size() == 0)
		{
			//////////////////////////////////////////////////////////////////////////
			//  主界面的延时会 影响到消息响应 [3/24/2017 ejitec]
			CEagleDeviceMgr::GetInstance()->MgrResumeStatusFetch();
			m_bRecPlay = false;
			
			WaitDisplayModuleDoneThread(1000);
			CEagleDeviceMgr::GetInstance()->MgrResumeStatusFetch();
			replay_status = EagleControlStart;
			UpdateAllTools(ECaptureReady, true);
			//qInfo() << GetLogFormat(EagleLog_I_Stop_Replay);
			emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Stop_Replay));
		}

		return;
	}

	// 开启  录像播放
	QList<QTreeWidgetItem*> items = ui.treeWidget_rec->selectedItems();
	if (items.size() == 0)
	{
		m_bRecPlay = false;
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Replay_Record));
		return;
	}

	m_CurPlayWnds.clear();
	
	QVariant data = items.at(0)->data(0, Qt::UserRole);  // 只取出第一个元素作为录像回放
	EagleData_Record_Id* record_id = data.value<EagleData_Record_Id*>();
	EagleData_Record *record = EagleDataMgr::GetInstance()->GetRecord(record_id);
	std::shared_ptr<EagleData_Record> spRecord  = std::make_shared<EagleData_Record>(*record);

	TINY_THREAD_BEGIN
	// 挂盘动作
	threadFun_remout(spRecord);

	qDebug() << "ThreadID Before doWorkInUi:" << QThread::currentThreadId();

	this->doWorkInUi_2([=]()
	{
		qDebug() << "ThreadID In doWorkInUi:" << QThread::currentThreadId();

		EagleData_Record_Id *record_id = &(spRecord->id);
		EagleData_CcdRecord* ccd_record = spRecord->ccd_record_list;

		ConfigExportReplayContext ctx;
		ctx.export_or_replay = CONFIG_TO_REPLAY;
		ctx.task_name = record_id->task_name;
		ctx.record_time = record_id->start_time;
		ctx.index_or_time = 100;

		while (ccd_record != 0)
		{
			ExportReplayContextCcd ctxccd;
			ctxccd.device_id = ccd_record->id.device_id;
			ctxccd.ccd_index = ccd_record->id.ccd_serial;
			ctxccd.start_frame_index = 0;
			ctxccd.end_frame_index = ccd_record->frame_number - 1;
			ctxccd.time_interval = 0;
			ctx.ccd_context.push_back(ctxccd);
			ccd_record = ccd_record->next;
		}

		recordSetDlg* recSetDlg = new recordSetDlg(&ctx, this);
		if (recSetDlg->exec() != QDialog::Accepted)
		{
			delete recSetDlg;
			recSetDlg = NULL;

			return;
		}
		
		ccd_record = spRecord->ccd_record_list;
		while (ccd_record != 0)  // 同时操作多路 播放
		{
			qDebug() << "select record: " << record_id->start_time << ", task:"
				<< QString::fromWCharArray(record_id->task_name);
			
			MessageCmd* ptcmd = new MessageCmd(GT_CMD_REPLAY_START);

			if (recSetDlg->getCMD(*ptcmd, ccd_record) != 0)
			{
				delete ptcmd;
				ptcmd = NULL;
				ccd_record = ccd_record->next;
				continue;
			}

			m_bRecPlay = true;

			QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
			if (curWnd)
			{
				m_CurPlayWnds.push_back(curWnd);
				qApp->postEvent(curWnd, ptcmd);
			}

			ccd_record = ccd_record->next;
		}

		if (m_bRecPlay)
		{
			replay_status = EagleControlContinue;
			UpdateAllTools(ECaptureReady, true);
			//qInfo() << GetLogFormat(EagleLog_I_Start_Replay);
			emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Start_Replay));
			CEagleDeviceMgr::GetInstance()->MgrPauseStatusFetch();
		}

		delete recSetDlg;
		recSetDlg = NULL;
	});

	TINY_THREAD_END
}

void EagleMainFrame::on_TExport()
{
	QList<QTreeWidgetItem*> items = ui.treeWidget_rec->selectedItems();
	if (items.size() == 0)
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Export_Record));
		return;
	}
	emit evt_rawLog(QtInfoMsg, GetLogFormat(EagleLog_I_Start_Export));
	vector<void*> recList = ui.treeWidget_rec->GetSelectedRecords();
	if (recList.size() == 1)
	{
		EagleData_Record *record = EagleDataMgr::GetInstance()->GetRecord((EagleData_Record_Id*)recList[0]);
		std::shared_ptr<EagleData_Record> spRecord = std::make_shared<EagleData_Record>(*record);

		doSingleExp(spRecord);
	}
	else
	{
		BatchExportContext ctx;
		for (auto it : recList)
		{
			ctx.remain_export_record.push_back((EagleData_Record_Id*)it);
		}

		doBatchExp(ctx);
	}
}

void EagleMainFrame::doSingleExp(std::shared_ptr<EagleData_Record> spRecord)
{
	TINY_THREAD_BEGIN
	// 挂盘动作
	threadFun_remout(spRecord);
	WaitDisplayModuleDoneThread(1000);

	this->doWorkInUi_2([=]()
	{
		EagleData_Record_Id *record_id = &(spRecord->id);
		ConfigExportReplayContext ctx;
		ctx.export_or_replay = CONFIG_TO_EXPORT;
		ctx.task_name = record_id->task_name;
		ctx.record_time = record_id->start_time;
		ctx.index_or_time = 0;

		EagleData_CcdRecord* ccd_record = spRecord->ccd_record_list;
		while (ccd_record != 0)
		{
			ExportReplayContextCcd ctxccd;
			ctxccd.device_id = ccd_record->id.device_id;
			ctxccd.ccd_index = ccd_record->id.ccd_serial;
			ctxccd.end_frame_index = ccd_record->frame_number - 1;
			ctxccd.start_frame_index = 0;
			ctxccd.time_interval = 0;
			ctx.ccd_context.push_back(ctxccd);
			ccd_record = ccd_record->next;
		}

		recordSetDlg* recSetDlg = new recordSetDlg(&ctx, this);
		if (recSetDlg->exec() != QDialog::Accepted)
		{
			delete recSetDlg;
			recSetDlg = NULL;

			return;
		}

		ccd_record = spRecord->ccd_record_list;
		while (ccd_record != 0)  // 同时操作多路 播放
		{
			qDebug() << "select record: " << record_id->start_time << ", task:"
				<< QString::fromWCharArray(record_id->task_name);

			MessageCmd* ptcmd = new MessageCmd(GT_CMD_EXPORT_START);

			if (recSetDlg->getCMD(*ptcmd, ccd_record) != 0)
			{
				delete ptcmd;
				ptcmd = NULL;
				ccd_record = ccd_record->next;
				continue;
			}

			QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
			if (curWnd)
			{
				qApp->postEvent(curWnd, ptcmd);
				qDebug() << "start replay "
					<< QString::fromWCharArray(record_id->task_name) << "-" << record_id->start_time
					<< ptcmd->Replay.replay_start_index;
			}

			ccd_record = ccd_record->next;
		}

		delete recSetDlg;
		recSetDlg = NULL;
		QtConcurrent::run(this, &EagleMainFrame::ExportWaitThread, GetLogFormat(EagleLog_M_Exporting)); // 线程属性
	});
	
	
	TINY_THREAD_END
}

void EagleMainFrame::doBatchExp(BatchExportContext& ctx)
{
	batchExport dlg(ctx, this);
	dlg.setModal(false);
	dlg.exec();
}

// 删除
void EagleMainFrame::on_TDel()
{
// 	if (cap_status_expected != ECaptureReady)
// 		return;
	if (IsDisplayPanelInDisplaying(false) == true)
		return;
	
	if (ui.treeWidget_rec->selectedItems().size() == 0)
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Delete_Record));

		return;
	}

	pwdDlg dlg(this);
	if (dlg.exec() == QDialog::Accepted)
	{
		TINY_THREAD_BEGIN

		std::vector<void*> select_records = ui.treeWidget_rec->GetSelectedRecords();
		Wait(GetLogFormat(EagleLog_M_Deleting_Records));
		for (std::vector<void*>::iterator it = select_records.begin(); it != select_records.end(); it++)
		{
			EagleData_Record_Id* record_id = (EagleData_Record_Id*)(*it);
			qDebug() << QString("select record: %1, task: %2").arg(record_id->start_time).arg(QString::fromWCharArray(record_id->task_name));
			try
			{
				EagleData_Record *record = EagleData_GetRecordAndAllocMemory(*record_id);
				EagleData_CcdRecord* ccd_record = record->ccd_record_list;
				
				int ret = 0;
				while (ccd_record != 0)
				{
					EagleData_DeleteRecord(*record_id, ccd_record->id);
					ccd_record = ccd_record->next;
				}
				EagleData_FreeRecordMemory(record);
				// 删除记录 %s
				ControlApiLogger(ret, EagleLog_C_Delete_Record, QString::fromWCharArray(record_id->task_name));
			}
			catch (std::runtime_error &){
				qDebug() << QString(" Failed Get record: %1, task: %2")
					.arg(record_id->start_time).arg(QString::fromWCharArray(record_id->task_name));

				continue;
			}
		}

		FinishWait();

		RefetchRecordListThread(true);

		TINY_THREAD_END
	}
}

//////////////////////////////////////////////////////////////////////////
// tasking related [3/6/2017 ejitec]

void EagleMainFrame::on_TPreview()
{
	if (/*IsDisplayPanelInDisplaying(false) == false*/m_CurPlayWnds.size() == 0)
	{
		std::vector<int> device_list;
		GetCheckedDeviceList(device_list);
		if (device_list.empty())
		{
			QMessageBox::about(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Task_Camera));
			return;
		}
		std::async(std::launch::async,&EagleMainFrame::StartPreviewThread, this);
	}
	else
	{
		std::async(std::launch::async,&EagleMainFrame::StopPreviewThread, this, false);
	}
}

int EagleMainFrame::StartDevicePreviewThread(int device_id)
{
	int ret = -1;
	ECaptureStatusType status = ECaptureReady;

	// 判断设备是否在task状态,如果不在tasking状态的话，则让设备进入tasking并通知显示模块进行显示
	// 如果在tasking状态，则只通知显示模块进行显示
	std::vector<eagle_capture_config> ccdlist = GetCcdList(device_id);
	for (auto it = ccdlist.begin(); it != ccdlist.end(); it++){
		if (it->capture_status == ECaptureRecording)
		{
			status = ECaptureRecording;
			break;
		}
		status = (ECaptureStatusType)it->capture_status > status ? (ECaptureStatusType)it->capture_status : status;
	}
	status = status >= ECaptureMax ? ECaptureReady : status;
	//ECaptureStatusType status = GetCurrentSystemStatus(device_id);
	ret = 0;
	if (status < ECaptureTasking)
	{
		//NEED DISCONNECT AOE
		DISK_MOUNT_TYPE type = DISK_MOUNT_NONE;
		type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
		int mode = CEagleDeviceMgr::GetInstance()->GetSdiMode(device_id);

		EagleData_RemoveFileSystem(device_id, type);
		int taskType = 0;
		if (mode > PixelSamplingGrey && mode < PixelSamplingMax)
			taskType = DATA_SOURCE_NORMAL_SDI;
		else if (mode == PixelSamplingGrey)
			taskType = DATA_SOURCE_NORMAL_CL;

		for (auto it = ccdlist.begin(); it != ccdlist.end(); it++){
			char shrink_level = 0;
			ret = EagleControl_GetCameraRealtimeShrinkLevel(device_id, it->camera_no, &shrink_level);
			EagleControl_SetCameraRealtimeShrinkLevel(device_id, it->camera_no, shrink_level);
		}

#if  (defined _DEBUG && !defined __LINUX__)

// 		case 0: self_check_type = DATA_SOURCE_CHECK_LINE; break;
// 		case 1: self_check_type = DATA_SOURCE_CHECK_COLUMN; break;
// 		case 2: self_check_type = DATA_SOURCE_CHECK_DIAGONAL; break;
// 		case 3: self_check_type = DATA_SOURCE_CHECK_MOVING_LINE; break;
// 		case 4: self_check_type = DATA_SOURCE_CHECK_MOVING_COLUMN; break;
// 		case 5: self_check_type = DATA_SOURCE_CHECK_MOVING_DIAGONAL; break;
		ret = EagleControl_StartTask(device_id, (wchar_t*)EagleConfigFile::getInstance()->task_name.toStdWString().c_str(), (int)DATA_SOURCE_CHECK_MOVING_LINE, mode);
#else
		// 开启任务 则相机前段端相机 就开始工作了
		ret = EagleControl_StartTask(device_id, (wchar_t*)EagleConfigFile::getInstance()->task_name.toStdWString().c_str(), taskType, mode);
		ControlApiLogger(ret, EagleLog_C_Start_Task, EagleConfigFile::getInstance()->task_name);
		//qInfo() << GetLogFormat(EagleLog_C_Start_Task).arg(EagleConfigFile::getInstance()->task_name).arg(ret);
#endif
	}
	if (ret != 0)
		return ret;

	// 通知模块显示
	for (auto it = ccdlist.begin(); it != ccdlist.end(); it++)
	{
		if (!EagleControl_IsCameraChecked(device_id, it->camera_no) || !EagleControl_IsCameraValid(device_id, it->camera_no))
			continue;
		MessageCmd cmd;
		cmd.cmd = GT_CMD_REALTIME_START_PLAY;
		cmd.device_id = device_id;
		cmd.ccd_serial = it->camera_no;
		cmd.column = it->column;
		cmd.line = it->line;
		cmd.frame_rate = it->frame_rate;
		cmd.color_depth = it->color_depth;
		cmd.sampling_format = CEagleDeviceMgr::GetInstance()->GetSdiMode(device_id);
		MessageCmd* ptcmd = new MessageCmd(cmd);
		QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
		if (curWnd)
		{
			m_CurPlayWnds.push_back(curWnd);
			qApp->postEvent(curWnd, ptcmd);
		}
	}
	return ret;
}

//  [3/6/2017 ejitec]
void EagleMainFrame::StartPreviewThread()
{
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	std::vector<std::future<int>> checker;
	bool task_start = false;

	Wait("");
	for (auto device_it = device_list.begin(); device_it != device_list.end(); device_it++)
	{
		checker.push_back(std::async(std::launch::async,&EagleMainFrame::StartDevicePreviewThread, this, *device_it));
	}

	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++)
		{
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1)))
			{
				all_check_thread_finished = false;
				break;
			}
		}

		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::milliseconds(50));
		else
			break;
	}

	for (auto it = checker.begin(); it != checker.end(); it++){
		if (it->get() == /*ERROR_SUCCESS*/0)
		{
			task_start = true;
			break;
		}
	}

	if (task_start)
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	FinishWait();

	if (task_start)
	{
		doWorkInUi_2([=]()
		{
			cap_status_expected = record_status == EagleControlContinue ? ECaptureRecording : ECaptureTasking;
			UpdateAllTools(cap_status_expected, true);
		});

	}

	last_cap_op_time = time(NULL);
}

// thread - 1 - 1 [3/6/2017 ejitec]
int EagleMainFrame::StopDevicePreviewThread(int device_id)
{
	int ret = -1;

	std::vector<eagle_capture_config> ccdlist = GetCheckedCcdList(device_id);
	for (auto it : m_DisplayWnds)
	{
		if (m_CurPlayWnds.contains(it))
		{
			MessageCmd* ptCmd = new MessageCmd(GT_CMD_REALTIME_STOP_PLAY);
			it->PostEvent(ptCmd); 	//stop display
		}
	}

	m_CurPlayWnds.clear();

	ECaptureStatusType cur_sys_status = GetCurrentSystemStatus(device_id);
	if (cur_sys_status == ECaptureTasking)
	{
		ret = EagleControl_StopTask(device_id);
		ControlApiLogger(ret, EagleLog_C_Stop_Task);
	}

	return ret;
}

// thread - 1
void EagleMainFrame::StopPreviewThread(bool judge_display_status)
{
	if (judge_display_status)
		if (IsDisplayPanelInDisplaying(false))
			return;
	Wait("");
	//判断是否正在记录
	std::vector<int> device_list;
	std::vector<std::future<int>> checker;

	GetCheckedDeviceList(device_list);
	for (std::vector<int>::iterator device_it = device_list.begin(); device_it != device_list.end(); device_it++)
	{
		checker.push_back(std::async(std::launch::async,&EagleMainFrame::StopDevicePreviewThread, this, *device_it));
	}

	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++)
		{
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1)))
			{
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
		else
			break;
	}

	bool all_preview_finished = true;
	for (auto it = checker.begin(); it != checker.end(); it++)
	{
		if (it->get() != 0)
		{
			all_preview_finished = false;
			break;
		}
	}

	FinishWait();
	if (all_preview_finished) 
	{
		cap_status_expected = record_status == EagleControlContinue ? ECaptureRecording : ECaptureReady;
	}

	
	doWorkInUi_2([=]()
	{
		WaitDisplayModuleDoneThread(1000);
		UpdateAllTools(cap_status_expected, true);
	});

	last_cap_op_time = time(NULL);
}


//////////////////////////////////////////////////////////////////////////
// record related [3/6/2017 ejitec]
void EagleMainFrame::StartRecordThread(int capture_frame_num, int capture_time, int capture_frame_interval)
{
	std::vector<int> device_list;
	std::vector<std::future<int>> checker;

	Wait("");
	GetCheckedDeviceList(device_list);
	for (auto device_it = device_list.begin(); device_it != device_list.end(); device_it++)
	{
		checker.push_back(std::async(std::launch::async,&EagleMainFrame::StartDeviceRecordThread, this, *device_it, capture_frame_num, capture_time, capture_frame_interval));
	}
	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++){
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1))){
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
		else
			break;
	}
	FinishWait();  // 同步鼠标等待 [11/23/2016 ejitec]
	doWorkInUi_2([=]()
	{
		// 状态更新
		record_status = EagleControlContinue;
		cap_status_expected = ECaptureRecording;
		last_cap_op_time = time(NULL);
		UpdateAllTools(cap_status_expected, true);
	});
}

int EagleMainFrame::StartDeviceRecordThread(int device_id, int capture_frame_num, int capture_time, int capture_frame_interval)
{
	int ret = -1;
	ECaptureStatusType status = GetCurrentSystemStatus(device_id);
	if (status < ECaptureTasking)
	{
		//NEED DISCONNECT AOE
		DISK_MOUNT_TYPE type = DISK_MOUNT_NONE;
		type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
		int mode = CEagleDeviceMgr::GetInstance()->GetSdiMode(device_id);
	
		EagleData_RemoveFileSystem(device_id, type);
		std::vector<eagle_capture_config> ccdlist = GetCcdList(device_id);
		for (auto it = ccdlist.begin(); it != ccdlist.end(); it++)
		{
			char shrink_level = 0;
			ret = EagleControl_GetCameraRealtimeShrinkLevel(device_id, it->camera_no, &shrink_level);
			EagleControl_SetCameraRealtimeShrinkLevel(device_id, it->camera_no, shrink_level);
		}
		int taskType = 0;
		if (mode > PixelSamplingGrey && mode < PixelSamplingMax)
			taskType = DATA_SOURCE_NORMAL_SDI;
		else if (mode == PixelSamplingGrey)
			taskType = DATA_SOURCE_NORMAL_CL;
		ret = EagleControl_StartTask(device_id, (wchar_t*)(EagleConfigFile::getInstance()->task_name.toStdWString().c_str()), taskType, mode);
		ControlApiLogger(ret, EagleLog_C_Start_Task, EagleConfigFile::getInstance()->task_name);
	}
	else ret = 0;

	if (ret != 0)
		return ret;

	ret = EagleControl_StartRecord(device_id, capture_frame_num, capture_time, capture_frame_interval);
	ControlApiLogger(ret, EagleLog_C_Start_Record, capture_time);
	return ret;
}

int	EagleMainFrame::StopDeviceRecordThread(int device_id, bool displaying)
{
	int ret = -1;
	ECaptureStatusType cur_sys_status = GetCurrentSystemStatus(device_id);
	if (cur_sys_status >= ECaptureRecording)
	{
		ret = EagleControl_StopRecord(device_id);
		ControlApiLogger(ret, EagleLog_C_StopRecord);
		QThread::msleep(500);
		if (displaying == false && ret == 0)
		{
			ret = EagleControl_StopTask(device_id);
			ControlApiLogger(ret, EagleLog_C_Stop_Task);
		}
	}
	return ret;
}

void EagleMainFrame::StopRecordThread()
{
	Wait("");
	//判断是否正在记录
	std::vector<int> device_list;
	std::vector<std::future<int>> checker;
	GetCheckedDeviceList(device_list);
	bool displaying = IsDisplayPanelInDisplaying(false);
	for (std::vector<int>::iterator device_it = device_list.begin(); device_it != device_list.end(); device_it++)
	{
		checker.push_back(std::async(std::launch::async,&EagleMainFrame::StopDeviceRecordThread, this, *device_it, displaying));
	}

	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++){
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1))){
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
		else
			break;
	}

	FinishWait();
	// 状态更新
	record_suspend_status = record_status = EagleControlStart;
	cap_status_expected = displaying ? ECaptureTasking : ECaptureReady;
	doWorkInUi_2([=]()
	{
		UpdateAllTools(cap_status_expected, true);
	});

	last_cap_op_time = time(NULL);
	std::async(std::launch::async,&EagleMainFrame::RefetchRecordListThread, this, true);
}

//记录 [11/17/2016 ejitec]
void EagleMainFrame::on_TRecord()
{
	std::vector<int> devicelist;
	GetCheckedDeviceList(devicelist);
	if (devicelist.empty())
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Task_Camera));

		return;
	}

	QString record_count = _toolcmb_dataNum->currentText();
	int seletion = _toolcmb_dataUnit->currentIndex();
	long rec_time = 0;
	long rec_interval = 0;
	long rec_fnm = 0;

	if (record_count.toLong() != 0)
	{
		if (RECORD_SECOND == seletion)
		{
			rec_time = record_count.toLong();
		}
		else
		{
			rec_time = record_count.toLong();
		}
	}
	if (record_status == EagleControlStart) 
	{
		if (cap_status_expected == ECaptureTasking)
		{
			if (IsDisplayPanelInDisplaying(false) == false)
			{
				std::async(std::launch::async,&EagleMainFrame::StopPreviewThread, this, false);
				return;
			}
		}

		if (rec_time < 10 && rec_time > 0)
		{
			QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Record_Time_Too_Less_Alarm));
			return;
		}
		record_type = rec_fnm == 0 ? RECORD_SECOND : RECORD_FNM;
		std::async(std::launch::async,&EagleMainFrame::StartRecordThread, this, rec_fnm, rec_time, rec_interval);
	}
	else if (record_status == EagleControlContinue)
	{
		record_type = RECORD_SECOND;
		std::async(std::launch::async,&EagleMainFrame::StopRecordThread, this);
	}
}

int EagleMainFrame::SuspendDeviceRecordThread(int device_id, bool bSuspend, int rec_fnm)
{
	int ret = -1;
	if (bSuspend)
	{
		ret = EagleControl_PauseRecord(device_id);
	}
	else
	{
		if (record_type == RECORD_FNM)
			ret = EagleControl_ContinueRecordByFrame(device_id, rec_fnm);
		else
			ret = EagleControl_ResumeRecord(device_id);
	}
	return ret;
}

void EagleMainFrame::SuspendRecordThread(bool bSuspend, int rec_fnm)
{
	std::vector<int> devicelist;
	std::vector<std::future<int>> checker;
	GetCheckedDeviceList(devicelist);
	Wait("");
	for (auto it = devicelist.begin(); it != devicelist.end(); it++)
	{
		checker.push_back(std::async(std::launch::async,&EagleMainFrame::SuspendDeviceRecordThread, this, *it, bSuspend, rec_fnm));
	}
	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++)
		{
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1)))
			{
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
		else
			break;
	}
	FinishWait();
	if (bSuspend)
	{
		record_suspend_status = EagleControlContinue;
		cap_status_expected = ECapturePaused;
	}
	else
	{
		record_suspend_status = EagleControlStart;
		cap_status_expected = ECaptureRecording;
	}
	last_cap_op_time = time(NULL);
	doWorkInUi_2([=]()
	{
		UpdateAllTools(cap_status_expected, true);
	});
}


// 暂停记录 [3/24/2017 ejitec]
void EagleMainFrame::on_TPauseRec()
{
	QString record_count = this->_toolcmb_dataNum->currentText();

	// pause & resume
	std::async(std::launch::async,&EagleMainFrame::SuspendRecordThread, this, record_suspend_status == EagleControlStart, record_count.toLong());
}

void EagleMainFrame::on_netWorkChange()
{
	destoryPlayWnds();
	ui.treeWidget_dev->clear();  // 
	ui.treeWidget_rec->clear();

	int default_selection = EagleConfigFile::getInstance()->conmunicate_method.toInt();
	if (default_selection == CONTROL_WINCAP)
	{
//		QtConcurrent::run(std::bind(&EagleMainFrame::ConnectWaitThread, this)); //ok
//		QtConcurrent::run(this, &EagleMainFrame::ConnectWaitThread);  // ok
		std::async(std::launch::async,&EagleMainFrame::ConnectWaitThread, this);
	}
	else
	{
	}
}


// 线程任务
void EagleMainFrame::ConnectWaitThread()
{
	Wait(GetLogFormat(EagleLog_M_Connecting_Device));

	[this]()
	{
		qDebug() << "ConnectWaitThread working ...";
		
		//  每次连接设备 清空上次设备 [12/1/2017 xystar]
		qDeleteAll(m_vDevList);
		m_vDevList.clear();

		eagle_all_netcards get_netcards;
		eagle_all_netcards set_netcards;
		EagleControl_GetSystemNICs(&get_netcards);
		QStringList eth_name = EagleConfigFile::getInstance()->eth_name;

		if (eth_name.empty())
			return;
		int ret = -1;
		memset(&set_netcards, 0, sizeof(set_netcards));
		for (int index = 0; index < eth_name.size(); index++)
		{
			for (int i = 0; i < get_netcards.card_num; i++)
			{
				if (eth_name[index].compare(get_netcards.cards[i].dev_description) == 0)
				{
					memcpy(&set_netcards.cards[set_netcards.card_num++], &get_netcards.cards[i], sizeof(eagle_netcard_info));
				}
			}
		}

		ret = EagleControl_SetControlNICs(&set_netcards);
		if (ret)
		{
			qDebug() << "EagleControl_SetControlNICs error!";

			return;
		}

		ControlApiLogger(0, EagleLog_C_Connect_Device);

		TCbJob tJob;
		tJob.m_eType = E_JOBTYPE_SCANNDEVLIST;

		CEagleDeviceMgr::GetInstance()->RescanDevices();
		emit evt_workFinish(tJob);

		tJob.m_eType = E_JOBTYPE_FETCHRECORDLIST;
		fetchRecList();
		emit evt_workFinish(tJob);

#ifdef CHENGGS_VERSION

		if (CHENGGS_VERSION == 3)
		{
			// 		wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, EagleToolIdStartPreview);
			// 		wxPostEvent(this->GetEventHandler(), e);
			// 		m_bCreatePlayWnds = false;
		}

#endif
	}();

	FinishWait();
}

void EagleMainFrame::on_DataMenuRescanRecList()
{
	std::vector<int> devices;
	GetAllDevice(devices);
	long file_value;
	DISK_MOUNT_TYPE type = DISK_MOUNT_NONE;
	file_value = EagleConfigFile::getInstance()->disk_mount_type.toLong();
	type = (DISK_MOUNT_TYPE)file_value;
	for (auto it = devices.begin(); it != devices.end(); it++)
	{
		EagleData_RemoveFileSystem((*it), type);
	}

	std::async(std::launch::async,&EagleMainFrame::RefetchRecordListThread, this, true);
}

void EagleMainFrame::FormatDiskThread()
{
	std::vector<std::future<void>> checker;
	std::vector<int> devices;

	CEagleDeviceMgr::GetInstance()->MgrPauseStatusFetch();
	GetCheckedDeviceList(devices);
	DISK_MOUNT_TYPE type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
	Wait(GetLogFormat(EagleLog_M_Formating_Disks));
	for (auto it = devices.begin(); it != devices.end(); it++)
	{
		int device_id = *it;
		checker.push_back(std::async(std::launch::async,[this, device_id, type]()
		{
			int res = 0;
			//NEED DISCONNECT AOE
			EagleData_RemoveFileSystem(device_id, type);
			res = EagleControl_ReformatDisk(device_id);
			if (res == 0)
			{
				res = EagleControl_ReinitDisk(device_id);
				ControlApiLogger(res, EagleLog_C_Format_Disks);
			}
		}));
	}
	while (true)
	{
		bool all_check_thread_finished = true;
		for (auto it = checker.begin(); it != checker.end(); it++){
			if (std::future_status::ready != it->wait_for(std::chrono::milliseconds(1))){
				all_check_thread_finished = false;
				break;
			}
		}
		if (all_check_thread_finished == false)
			std::this_thread::sleep_for(std::chrono::seconds(1));
		else
			break;
	}

	FinishWait();
	RefetchRecordListThread(false);
	doWorkInUi_2([this]() 
	{
		CEagleDeviceMgr::GetInstance()->MgrResumeStatusFetch();
	});
}

// system Menu
void EagleMainFrame::on_SysMenuFormatDisk()
{
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	if (device_list.empty())
	{
		QMessageBox::warning(this,GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Format_Device));
		return;
	}
	pwdDlg dlg(this);
	if (dlg.exec() == QDialog::Accepted)
	{
		std::async(std::launch::async,&EagleMainFrame::FormatDiskThread, this);
	}
}

void EagleMainFrame::on_SysMenutoFactory()
{
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	if (device_list.empty())
	{
		QMessageBox::warning(this,GetMessageBoxTitle(),GetLogFormat(EagleLog_M_Select_Non_Restore_Device));
		return;
	}
	
	int nRet = QMessageBox::question(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Reset_Factory_Alarm));

// 	wxMessageDialog dlg(GetParent(), W, GetMessageBoxTitle(), wxOK | wxCANCEL);
// 	dlg.SetOKCancelLabels(wxMessageDialogBase::ButtonLabel(GetMessageDlgButton(EAGLE_MSG_DLG_OK)),
// 		wxMessageDialogBase::ButtonLabel(GetMessageDlgButton(EAGLE_MSG_DLG_CANCEL)));
	if (nRet == QMessageBox::Ok) 
	{
		std::vector<int> devicelist;
		GetCheckedDeviceList(devicelist);
		for (auto it = devicelist.begin(); it != devicelist.end(); it++)
		{
			int ret = EagleControl_RestoreConfig(*it);
			ControlApiLogger(ret, EagleLog_C_Restore_Factory_Setting);
		}
	}
}


void EagleMainFrame::RefetchRecordListThread(bool show_info)
{
	//wxBusyCursor wait_curser;
	if (show_info)
	{
		Wait(GetLogFormat(EagleLog_M_Fetching_Record_List));
	}
	else
	{
		Wait(QString(""));
	}
	std::this_thread::sleep_for(std::chrono::seconds(1));
	EagleData_RefetchRecList();

	TCbJob tJob;
	tJob.m_eType = E_JOBTYPE_FETCHRECORDLIST;
	m_ptJobHander->postJob([this]()  // 线程任务 
	{
		fetchRecList();

		return true;

	}, tJob);

	FinishWait();
}

// dataMenu
void EagleMainFrame::on_DataMenuRename()
{
	if (IsDisplayPanelInDisplaying(false) == true)
		return;

	QList<QTreeWidgetItem*> items = ui.treeWidget_rec->selectedItems();
	if (items.size() == 0)
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Rename_Record));
		return;
	}

	static std::vector<void*> select_records;
	select_records.clear();
	pwdDlg dlg(this);
	select_records = ui.treeWidget_rec->GetSelectedRecords();
	if (dlg.exec() == QDialog::Accepted)
	{
		renameDlg Rnmdlg(this);
		if (Rnmdlg.exec() == QDialog::Accepted)
		{
			QString strText = Rnmdlg.getNewName();
			TINY_THREAD_BEGIN
			wchar_t wszNewNam[32] = { 0 };
			strText.toWCharArray(wszNewNam);
			
			Wait(GetLogFormat(EagleLog_M_Renaming_Task));

			for (std::vector<void*>::iterator it = select_records.begin(); it != select_records.end(); it++)
			{
				EagleData_Record_Id* record_id = (EagleData_Record_Id*)(*it);
				qDebug() << tr("select record: %1, task: %2")
					.arg(record_id->start_time).arg(QString::fromWCharArray(record_id->task_name));
				int ret = EagleData_RenameTask(*record_id, wszNewNam);
				ControlApiLogger(ret, EagleLog_C_Rename_Task, QString::fromWCharArray(record_id->task_name), QString::fromWCharArray(wszNewNam));
			}

			FinishWait();

			RefetchRecordListThread();

			TINY_THREAD_END
		}
	}
}

void EagleMainFrame::Wait(QString stInfo)
{
	doWorkInUi_2([=]()
	{
		ui.statusBar->PushStatus(stInfo);
		// 设置状态动作 [12/1/2016 ejitec]
		this->menuBar()->setDisabled(true);
		ui.mainToolBar->setDisabled(true);
		ui.splitter->widget(0)->setDisabled(true);
		//this->statusBar()->setEnabled(true);
		qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
	});
}

void EagleMainFrame::FinishWait()
{
	doWorkInUi_2([=]()
	{
		ui.statusBar->PopStatus();
		this->menuBar()->setEnabled(true);
		ui.mainToolBar->setEnabled(true);
		//ui.splitter->setEnabled(true);
		ui.splitter->widget(0)->setEnabled(true);
		qApp->restoreOverrideCursor();
	});
}

// 以毫秒计时
void EagleMainFrame::WaitDisplayModuleDoneThread(int timeout)
{
	if (timeout < 1)
		timeout = 1;

	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
	
	for (int i = 0; i < timeout/10; i++)  // cpu延时粒度
	{
		bool wait = false;
		for (auto it : m_DisplayWnds)
		{
			if (it->IsDisplayIng())
			{
				wait = true;
				break;
			}
		}
		if (!wait)
			break;
		std::this_thread::sleep_for(std::chrono::milliseconds(10));
		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
	}

	qApp->restoreOverrideCursor();
}

void EagleMainFrame::ExportWaitThread(QString wait_msg)
{
	CEagleDeviceMgr::GetInstance()->MgrPauseStatusFetch();

	Wait(wait_msg);
	std::this_thread::sleep_for(std::chrono::seconds(2));

	for (;;) 
	{
		bool wait = false;
		for (auto it : m_DisplayWnds)
		{
			if (it->IsExpOrCheck())
			{
				wait = true;
			}
		}
		if (!wait)
			break;
		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
		std::this_thread::sleep_for(std::chrono::milliseconds(500));
	}
	FinishWait();

	CEagleDeviceMgr::GetInstance()->MgrResumeStatusFetch();
}

// 等待 显示窗口展示 [4/6/2017 ejitec]
bool EagleMainFrame::IsDisplayPanelInDisplaying(bool need_delay)
{
	bool isDisplaying = false;
	int nCnt = 20;

	if (need_delay)
	{
	//	std::this_thread::sleep_for(std::chrono::milliseconds(200));
 		qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
 		do 
 		{
 			QThread::usleep(1000);  // 直接sleep 会 阻塞 消息转发
 			qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
 		} while (--nCnt > 0);
 		qApp->restoreOverrideCursor();
	}
		
	
	for (auto it : m_DisplayWnds)
	{
		if (it->IsDisplayIng())
		{
			isDisplaying = true;
			break;
		}
	}

	return isDisplaying;
}

//数据-检查 数据
void EagleMainFrame::on_CheckData()
{
	if (ui.treeWidget_rec->selectedItems().size() == 0)
	{
		QMessageBox::warning(this, GetMessageBoxTitle(), GetLogFormat(EagleLog_M_Select_Non_Datacheck_Record));
		return;
	}

	TINY_THREAD_BEGIN

	remountBySelRecords();
	WaitDisplayModuleDoneThread(5*1000);

	//以下必须在主线程中运行
	doWorkInUi_2([=]()
	{
		std::vector<void*> select_records = ui.treeWidget_rec->GetSelectedRecords();
		if (select_records.empty()) 
		{
			QMessageBox::warning(this, GetMessageBoxTitle(),GetLogFormat(EagleLog_M_Select_Non_Replay_Record));
			return;
		}
		for (std::vector<void*>::iterator it = select_records.begin(); it != select_records.end(); it++)
		{
			EagleData_Record_Id* record_id = (EagleData_Record_Id*)(*it);
			//Debug(L"select record: %ld, task: %s", record_id->start_time, record_id->task_name);
			try{
				EagleData_Record *record = EagleDataMgr::GetInstance()->GetRecord(record_id);
				EagleData_CcdRecord* ccd_record = record->ccd_record_list;
				while (ccd_record != 0)
				{
					MessageCmd* ptcmd = new MessageCmd(GT_CMD_CHECK_DATA);
					MessageCmd&cmd = *ptcmd;
					wcscpy(cmd.task_name, record_id->task_name);
					cmd.task_index = ccd_record->task_index;
					cmd.record_time = record_id->start_time;
					cmd.device_id = ccd_record->id.device_id;
					cmd.ccd_serial = ccd_record->id.ccd_serial;
					cmd.line = ccd_record->line;
					cmd.column = ccd_record->column;
					cmd.color_depth = ccd_record->color_depth;
					cmd.frame_rate = 0;//NOT USE
					cmd.record_index = ccd_record->record_index;
					cmd.interval = 1;  // 不抽帧
					cmd.replay_export_method = 0;  //安 帧号
					cmd.frame_time_interval = 0;
					cmd.Export.export_start_index = 0;
					// 底层传递：网口 uint --> long  64位系统不对齐
					cmd.Export.export_end_index = ccd_record->frame_number - 1;
					cmd.Export.export_type = 0;
					cmd.Export.export_decode_method = 0;
					wcscpy(cmd.Export.export_path, L"");
					QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
					if (curWnd)
					{
						m_CurPlayWnds.push_back(curWnd);
						qApp->postEvent(curWnd, ptcmd);
					}
					ccd_record = ccd_record->next;
				}
			}
			catch (std::runtime_error &e)
			{
				qDebug() << QString(" %1:%2 %3").arg(e.what())
					.arg(QString::fromWCharArray(record_id->task_name)).arg(record_id->start_time);
				return;
			}
			break;
		}
		QtConcurrent::run(this, &EagleMainFrame::ExportWaitThread, GetLogFormat(EagleLog_M_Checking_Error_Rate)); // 线程属性
		//std::async(std::launch::async,&EagleMainFrame::ExportWaitThread, this, );
	});


	TINY_THREAD_END

}

// 数据-自检 [3/20/2017 ejitec]
void EagleMainFrame::on_CheckRecord()
{
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	if (device_list.empty())
	{
		QMessageBox::warning(this, GetMessageBoxTitle(),GetLogFormat(EagleLog_M_Select_Non_Selfcheck_Camera));
		return;
	}

	_timer->stop();
	DISK_MOUNT_TYPE type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
	// 自检dlg
	checkRecordDlg dlg(this);
	int nRet = dlg.exec();
	if (nRet == QEvent::User)
	{
		record_status = EagleControlContinue;
		cap_status_expected = ECaptureRecording;

		for (auto device_it = device_list.begin(); device_it != device_list.end(); device_it++)
		{
			int device_id = (*device_it);
			//NEED DISCONNECT AOE
			EagleData_RemoveFileSystem(device_id, type);
			std::vector<eagle_capture_config> ccdlist = GetCheckedCcdList(*device_it);
			for (auto it = ccdlist.begin(); it != ccdlist.end(); it++){
				MessageCmd* ptcmd = new MessageCmd(GT_CMD_REALTIME_START_PLAY);
				MessageCmd& cmd = *ptcmd;
				cmd.device_id = device_id;
				cmd.ccd_serial = it->camera_no;
				cmd.column = it->column;
				cmd.line = it->line;
				cmd.frame_rate = it->frame_rate;
				cmd.color_depth = it->color_depth;
				cmd.sampling_format = 0;

				QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
				if (curWnd)
				{
					m_CurPlayWnds.push_back(curWnd);
					qApp->postEvent(curWnd, ptcmd);
					UpdateAllTools(cap_status_expected, true);
				}
			}
		}
	}
	else if (nRet == QEvent::User + 1)
	{
		cap_status_expected = ECaptureTasking;
		for (auto device_it = device_list.begin(); device_it != device_list.end(); device_it++)
		{
			int device_id = (*device_it);
			//NEED DISCONNECT AOE
			EagleData_RemoveFileSystem(device_id, type);
			std::vector<eagle_capture_config> ccdlist = GetCheckedCcdList(*device_it);
			for (auto it = ccdlist.begin(); it != ccdlist.end(); it++)
			{
				MessageCmd* ptcmd = new MessageCmd(GT_CMD_REALTIME_START_PLAY);
				MessageCmd& cmd = *ptcmd;
				cmd.device_id = device_id;
				cmd.ccd_serial = it->camera_no;
				cmd.column = it->column;
				cmd.line = it->line;
				cmd.frame_rate = it->frame_rate;
				cmd.color_depth = it->color_depth;
				cmd.sampling_format = 0;

				QDisPlayWidget* curWnd = getPlayWndBy(ptcmd->device_id, ptcmd->ccd_serial);
				if (curWnd)
				{
					m_CurPlayWnds.push_back(curWnd);
					qApp->postEvent(curWnd, ptcmd);
				}
			}
		}
	}
	else  //QDialog::Rejected
	{
		_timer->start();
		
		return;
	}

	// 使能按鈕 [12/2/2016 ejitec]
	UpdateAllTools(cap_status_expected, true);  
	last_cap_op_time = time(NULL);
	_timer->start();
}

void EagleMainFrame::toFull(bool bfull)
{
	if (m_nCameraCnt == 1)
	{
		return;
	}

	bfull ? _smallWndScroll->hide() : _smallWndScroll->show();
	
	return ;
}


void EagleMainFrame::toNormal(BaseDisParentWnd* curWnd)
{
	_hLayoutOut->removeWidget(_smallWndScroll);
	curWnd->setParent(ui.widget_View);
	_hLayoutOut->addWidget(curWnd, 4);
	_hLayoutOut->addWidget(_smallWndScroll, 1);
}


// 与仿真相关操作 [11/24/2017 xystar]

void EagleMainFrame::on_SimuMenuDataImport()
{
#ifdef SIMULATE_HAS_IMPLEMENTED
	
	int device_id = 0;
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	if (device_list.empty())
	{
		wxMessageBox(GetLogFormat(EagleLog_M_Select_Non_Operate_Device), GetMessageBoxTitle());
		return;
	}

	device_id = *device_list.begin();
	if (GetCurrentSystemStatus(device_id) != ECaptureReady)
		return;
	if (IsDisplayPanelInDisplaying(false) == true)
		return;

	std::function< void(int devID)> pfun = [this](int device_id)
	{
		Wait(GetLogFormat(EagleLog_M_Mounting_Disk));
		DISK_MOUNT_TYPE type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
		int ret = EagleData_CheckAndRemountFileSystem(device_id, type);
		FinishWait();

		doWorkInUi_2([this, device_id]()
		{
			CEvfsCfgDlg* dlg = new CEvfsCfgDlg(device_id, this);
			dlg->exec();
			delete dlg;
			dlg = NULL;

			long file_value;
			DISK_MOUNT_TYPE type = (DISK_MOUNT_TYPE)EagleConfigFile::getInstance()->disk_mount_type.toLong();
			EagleData_UpdateDeviceExpList(device_id);
			EagleData_RemoveFileSystem(device_id, type);
			std::async(&EagleMainFrame::RefetchRecordListThread, this, true);
		});
	};

	std::async(std::launch::async, pfun, device_id);
	
#endif
}

void EagleMainFrame::on_SimuMenuPaly()
{
	std::vector<int> device_list;
	GetCheckedDeviceList(device_list);
	if (device_list.empty()){
		wxMessageBox(GetLogFormat(EagleLog_M_Select_Non_Operate_Device), GetMessageBoxTitle());
		return;
	}

	for (auto device_id : device_list)
	{
		if (GetCurrentSystemStatus(device_id) != ECaptureReady)
			return;
	}
	
	if (IsDisplayPanelInDisplaying(false) == true)
		return;

	//CEagleDeviceMgr::GetInstance()->MgrPauseStatusFetch();
	CSimulaPlayDlg dlg(m_vDevList,this);
	dlg.setWindowIcon(this->windowIcon());
	dlg.exec();
	//CEagleDeviceMgr::GetInstance()->MgrResumeStatusFetch();
}

// 仿真主窗口 [11/24/2017 xystar]
CSimulaPlayDlg::CSimulaPlayDlg(QVector<TDevWithCCDInfo*>& devList, QWidget* parent)
:QDialog(parent), _tDevsInfo(devList), m_bPause(false)
{
	ui.setupUi(this);
	setCtrlButtonStatus(false);

	this->setWindowFlags(this->windowFlags()| Qt::WindowMinMaxButtonsHint);
	this->setMinimumSize(800,600);
	ui.wgt_display->setMinimumWidth(200);
	_disPlayHL = new QHBoxLayout(ui.wgt_display);
	_disPlayHL->setSpacing(2); // 水平间隔2个像素
	_disPlayHL->setContentsMargins(0,0,0,0);  //  margin为0 缩放回来没有了
	//_disPlayHL->setContentsMargins(0,0, -1, -1); 


	GetCheckedDeviceList(_checkDevs);
	QVector<int> checkDevs = QVector<int>::fromStdVector(_checkDevs);

	for (auto dev : _tDevsInfo)
	{
		if (checkDevs.contains(dev->m_nDevID))
		{
			ui.tabWidget->addTab(new CSimuPlayInfoWgt(dev->m_nDevID, dev->m_strDevNam, this),dev->m_strDevNam);
		}
	}

	QTimer::singleShot(0, [this]()
	{
		this->showMaximized();
		createPlayWnds();
	});

	connect(ui.btn_start, &QPushButton::clicked, this, &CSimulaPlayDlg::on_buttonStartExportOnButtonClick);
	connect(ui.btn_stop, &QPushButton::clicked, this, &CSimulaPlayDlg::on_buttonStopExportOnButtonClick);
	connect(ui.btn_prev, &QPushButton::clicked, this, &CSimulaPlayDlg::on_tPrevSimullateClicked);
	connect(ui.btn_next, &QPushButton::clicked, this, &CSimulaPlayDlg::on_tNextSimullateClicked);
	connect(ui.btn_play, &QPushButton::clicked, this, &CSimulaPlayDlg::on_tPlayPauseSimullateClicked);
	ui.splitter->setSimuMode();
	ui.splitter->setSimuMain(this);
}

void CSimulaPlayDlg::toFull(QDisPlayWidget* curWnd, bool bFull)
{
	for (auto& it : m_BaseDisWnds)
	{
		if (it->DisPlayWnd() != curWnd)
		{
			bFull ? it->hide() : it->show();
		}
	}

// 	if (!bFull)
// 	{
// 		QTimer::singleShot(10, [this]()
// 		{
// 			ui.splitter->setCollapsible(1,true);
// 		});
// 	}

	qDebug() << "ui.wgt_display:" << bFull << ui.wgt_display->size() << " isCollapsible:" << ui.splitter->isCollapsible(1)
		<< " wgtCnt:" << ui.splitter->count();
}

void CSimulaPlayDlg::toNormal(BaseDisParentWnd* curWnd)
{
	if (m_BaseDisWnds.size() == 1)
	{
		curWnd->setParent(ui.wgt_display);
		_disPlayHL->addWidget(curWnd);

		return;
	}

	while (_disPlayHL->count())
	{
		_disPlayHL->removeItem(_disPlayHL->itemAt(0));
	}

	for (auto& it : m_BaseDisWnds)
	{
		_disPlayHL->addWidget(it);
	}
}

void CSimulaPlayDlg::createPlayWnds()
{
	QVector<int> checkDevs = QVector<int>::fromStdVector(_checkDevs);
	for (auto dev : _tDevsInfo)
	{
		if (!checkDevs.contains(dev->m_nDevID))
		{
			continue;
		}

		TCCDInfo& ccd = dev->m_vCCDInfo[0];
		
		BaseDisParentWnd* Basewnd = new BaseDisParentWnd(ui.wgt_display, ccd, dev->m_strDevNam, QString("%1_%2_%3")
			.arg(dev->m_strDevNam).arg(ccd.m_strCCDNam).arg(1));
		QDisPlayWidget* wnd = Basewnd->DisPlayWnd();
		//connect(wnd, &QDisPlayWidget::evt_stopRec, this, &EagleMainFrame::on_TRecPlay);
		wnd->installEventFilter(ui.splitter);
		Basewnd->setSimulateUi();
		Basewnd->setMinimumWidth(100);
		wnd->DevID(dev->m_nDevID);
		wnd->CCDID(ccd.m_tInfo.camera_no);
		wnd->InCenter(true);
		m_DisplayWnds << wnd;
		m_BaseDisWnds << Basewnd;
		_disPlayHL->addWidget(Basewnd);
	}
}

void CSimulaPlayDlg::destoryPlayWnds()
{
	QLayoutItem* child = nullptr;  // 删除所有的 strech
	while ((child = _disPlayHL->takeAt(0)) != 0)
	{
		delete child;
		child = nullptr;
	}

	qDeleteAll(m_BaseDisWnds);
	m_BaseDisWnds.clear();
	m_DisplayWnds.clear();
}

CSimulaPlayDlg::~CSimulaPlayDlg()
{
	qDebug() << "CSimulaPlayDlg begin  -->>";
	destoryPlayWnds();
	qDebug() << "<<-- CSimulaPlayDlg end!!";

}

QDisPlayWidget* CSimulaPlayDlg::getPlayWndBy(int devID, int ccdID)
{
	for (auto it : m_DisplayWnds)
	{
		if (it->CCDID() == ccdID && it->DevID() == devID)
		{
			return it;
		}
	}

	return nullptr;
}

void CSimulaPlayDlg::checkIsAllStop()
{
	bool allStop = true;
	// 设置各个 NoteBook Page
	for (int n = 0; n < ui.tabWidget->count(); n++)
	{
		CSimuPlayInfoWgt* panel = (CSimuPlayInfoWgt*)ui.tabWidget->widget(n);
		if (!panel->IsStop())
		{
			allStop = false;
			break;
		}
	}

	if (allStop)
	{
		setCtrlButtonStatus(false);
	}
}

void CSimulaPlayDlg::setCtrlButtonStatus(bool bPlayOK)
{
	ui.btn_start->setEnabled(!bPlayOK);
	ui.btn_stop->setEnabled(bPlayOK);
	ui.btn_play->setEnabled(bPlayOK);
	ui.btn_prev->setEnabled(bPlayOK);
	ui.btn_next->setEnabled(bPlayOK);

	
	if (!bPlayOK)
		ui.btn_play->setText(tr("暂停"));
}

void CSimulaPlayDlg::on_buttonStartExportOnButtonClick()
{
	bool bPlayOK = false;
	// 设置各个 NoteBook Page
	for (int n = 0; n < ui.tabWidget->count(); n++)
	{
		CSimuPlayInfoWgt* panel = (CSimuPlayInfoWgt*)ui.tabWidget->widget(n);
		if (panel->toStartSimuPlay())
		{
			bPlayOK = true;
		}
	}
	setCtrlButtonStatus(bPlayOK);
}

void CSimulaPlayDlg::on_buttonStopExportOnButtonClick()
{
	// 由各个 子配置窗口  判断 全局按钮使能 [11/21/2017 xystar]
	for (int n = 0; n < ui.tabWidget->count(); n++)
	{
		CSimuPlayInfoWgt* panel = (CSimuPlayInfoWgt*)ui.tabWidget->widget(n);
		panel->on_StopSimuPlay();
	}
}

void CSimulaPlayDlg::on_tPrevSimullateClicked()
{
	for (auto& it : m_DisplayWnds)
	{
		it->on_btnPrev();
	}
}

void CSimulaPlayDlg::on_tNextSimullateClicked()
{
	for (auto& it : m_DisplayWnds)
	{
		it->on_btnNext();
	}
}

void CSimulaPlayDlg::on_tPlayPauseSimullateClicked()
{
	m_bPause = !m_bPause;
	
	for (auto& it : m_DisplayWnds)
	{
		it->on_btnPlay();
	}

	if (m_bPause)
	{
		ui.btn_play->setText(tr("播放"));
	}
	else
	{
		ui.btn_play->setText(tr("暂停"));
	}
}

void CSimulaPlayDlg::closeEvent(QCloseEvent *e)
{
	if (!ui.btn_start->isEnabled())
	{
		wxMessageBox(tr("当前仿真播放状态,请先停止后关闭仿真窗口!!"), tr("提示"));
		e->ignore();

		return;
	}

	return QDialog::closeEvent(e);
}


CSimuPlayInfoWgt::CSimuPlayInfoWgt(int ndev,QString title, QWidget* parent /*= NULL*/)
:QWidget(parent), _devID(ndev), _PanelNam(title)
{
	ui.setupUi(this);
	this->setWindowTitle(parent->windowTitle());
	this->setWindowIcon(parent->windowIcon());
	ui.btn_stop->setEnabled(false);
	ui.lineEdit_colum->setEnabled(false);
	ui.lineEdit_row->setEnabled(false);
	ui.lineEdit_depth->setEnabled(false);
	
// 	ui.groupBox->setAutoFillBackground(true);
// 	QPalette pt = ui.groupBox->palette();
// 	pt.setBrush(QPalette::Background, Qt::gray);
// 	ui.groupBox->setPalette(pt);

	uint32_t values[] = {
		40000000, 65000000, 75000000, 80000000,
		85000000, 50000000, 60000000, 29500000,
		30000000, 11600000
	};

	_parent = qobject_cast<CSimulaPlayDlg*>(parent);
	Q_ASSERT(_parent);
	ui.cmb_hz->clear();
	for (u_int i = 0; i < ARRAYSIZE(values); i++)
	{
		if (values[i] % 1000000 != 0)
			ui.cmb_hz->addItem(QString("").sprintf("%0.1f MHz", values[i] / 1000000.0));
		else
			ui.cmb_hz->addItem(QString("").sprintf("%d MHz", values[i] / 1000000));
	}
	ui.cmb_hz->setCurrentIndex(0);

	QVector<EagleData_Record_Id*>& recList = g_theApp->getRecList();

	ui.recTree->clearSelection();
	ui.recTree->clear();
	ui.recTree->setSelectionBehavior(QTreeWidget::SelectionBehavior::SelectRows);
	ui.recTree->setSelectionMode(QTreeWidget::SelectionMode::SingleSelection);

	if (recList.size() == 0)
	{
		return;
	}

	ui.groupBox->setTitle(title);
	ui.recTree->setHeaderLabels(QStringList() << _PanelNam);
	for (auto rec : recList)
	{
		AppendRecord(rec);
	}

	qDebug() << "topLevelItemCount:" << ui.recTree->topLevelItemCount();
	ui.recTree->expandAll();


	connect(ui.recTree, &QTreeWidget::itemClicked, [this](QTreeWidgetItem *item, int column)
	{
		if (item->type() == ITEM_PARENT)
		{
			return;
		}

		EagleData_Record_Id* record_id = item->data(0,Qt::UserRole).value<EagleData_Record_Id*>();
		if (record_id == NULL)
		{
			return ;
		}

		EnableSelect(false, 0, 0, 0, 0, 0, 0);

		EagleData_Record* eagle_record = EagleDataMgr::GetInstance()->GetRecord(record_id);

		if (eagle_record == 0)
			return;

		EagleData_CcdRecord* ccd_record = 0;

		ccd_record = eagle_record->ccd_record_list;
		while (ccd_record != 0)
		{
			if (ccd_record->id.device_id == _devID)
			{
				EnableSelect(ccd_record->frame_number != 0, ccd_record->frame_number, ccd_record->column, ccd_record->line, ccd_record->real_color_depth, ccd_record->task_index, ccd_record->record_index);
				break;
			}
			ccd_record = ccd_record->next;
		}
	});

	connect(ui.btn_start, &QPushButton::clicked, this, &CSimuPlayInfoWgt::on_StartSimuPlay);
	connect(ui.btn_stop, &QPushButton::clicked, this, &CSimuPlayInfoWgt::on_StopSimuPlay);
}

MessageCmd* CSimuPlayInfoWgt::PrepareStartExp()
{
	bool bRet = false;
	bool checked = 0;
	long start_frame = 0;
	long stop_frame = 0;
	long interval = 0;
	unsigned short frame_rate = 25;
	unsigned char frame_taps = 2;
	unsigned char clock_hz = 0;
	unsigned short column = 0;
	unsigned short line = 0;
	unsigned short color_depth = 0;
	MessageCmd* ptCmd = nullptr;

	do
	{
		if (ui.recTree->selectedItems().size() == 0)
			break;

		QTreeWidgetItem* item = ui.recTree->selectedItems()[0];
		EagleData_Record_Id* record_id = item->data(0, Qt::UserRole).value<EagleData_Record_Id*>();

		if (item->type() == ITEM_PARENT)
		{
			wxMessageBox(tr("请选择记录\n设备:%1").arg(_PanelNam),this->windowTitle(),this);
			break;
		}

		if (this->isEnabled() == false)
		{
			wxMessageBox(tr("请选择有效记录\n设备:%1").arg(_PanelNam), this->windowTitle(), this);
			break;
		}

		GetConfig(start_frame, stop_frame, interval, frame_rate, frame_taps, clock_hz, column, line, color_depth);
		// fix <= to  < [8/18/2017 xystar]
		if (stop_frame < start_frame)
		{
			wxMessageBox(tr("帧数参数错误\n设备:%1").arg(_PanelNam), this->windowTitle(), this);
			break;
		}

		int bsuccess = is_camlink_export_param_valid(clock_hz, column, line, frame_taps, frame_rate);

		if (bsuccess <= 0)
		{
			wxMessageBox(tr("导出参数设置错误\r\n帧频不支持\n设备:%1").arg(_PanelNam), this->windowTitle(), this);
			break;
		}
		
		ptCmd = new MessageCmd(GT_CMD_REPLAY_START);  // 由Qt事件 循环释放 
		MessageCmd& cmd = *ptCmd;
		//memset(&cmd, 0x00, sizeof(cmd));
		wcscpy(cmd.task_name, record_id->task_name);
		cmd.device_id = _devID;
		cmd.ccd_serial = 1;
		cmd.line = line;
		cmd.column = column;
		cmd.color_depth = color_depth;
		cmd.frame_rate = 0;//NOT USE
		cmd.record_time = record_id->start_time;
		cmd.Simu.start_frame = start_frame;
		cmd.Simu.read_frame_num = stop_frame - start_frame + 1;
		cmd.Simu.frame_rate = frame_rate;
		cmd.Simu.frame_taps = frame_taps;
		cmd.replay_export_method = 3;

		int ret = EagleData_CameralinkSetClock(_devID, clock_hz);
		if (ret != 0)
		{
			wxMessageBox(tr("设置仿真时钟失败:%1\n设备:%1").arg(ret).arg(_PanelNam), this->windowTitle(), this);
			break;
		}

		bRet = true;

	} while (0);

	if (!bRet)
	{
		delete ptCmd;
		ptCmd = nullptr;
	}


	return ptCmd;
}

int CSimuPlayInfoWgt::is_camlink_export_param_valid(char clock_hz, int column, int line, int frame_taps, int frame_rate)
{
	int value = 0;
	int clock_fps = 0;
	switch (clock_hz)
	{
	case 0: clock_fps = 40000000; break;
	case 1: clock_fps = 65000000; break;
	case 2: clock_fps = 75000000; break;
	case 3: clock_fps = 80000000; break;
	case 4: clock_fps = 85000000; break;
	case 5: clock_fps = 50000000; break;
	case 6: clock_fps = 60000000; break;
	case 7: clock_fps = 29500000; break;
	case 8: clock_fps = 30000000; break;  //
	case 9: clock_fps = 11600000; break;
	default:
		return -1;
		break;
	}
	value = clock_fps / (frame_rate * line) - column / frame_taps;
	return value;
}

void CSimuPlayInfoWgt::AppendRecord(EagleData_Record_Id* record_id)
{
	EagleData_Record* eagle_record = EagleData_GetRecordAndAllocMemory(*record_id);
	if (eagle_record == NULL)
		return;

	EagleData_CcdRecord* ccd_record = 0;
	ccd_record = eagle_record->ccd_record_list;

	while (ccd_record != 0)
	{
		if (ccd_record->id.device_id != _devID)
		{
			ccd_record = ccd_record->next;
			continue;
		}

		QTreeWidgetItem* head = ui.recTree->headerItem();
		QTreeWidgetItem* hearditem = NULL;
		QList<QTreeWidgetItem*> itemList = ui.recTree->findItems(QString::fromWCharArray(record_id->task_name), Qt::MatchStartsWith);
		if (itemList.size() == 0)
		{
			hearditem = new QTreeWidgetItem(ui.recTree,
				QStringList() << QString::fromWCharArray(record_id->task_name), ITEM_PARENT);
			hearditem->sortChildren(0, Qt::AscendingOrder);
		}
		else
		{
			hearditem = itemList[0];
		}

		QDateTime dt = QDateTime::fromTime_t(record_id->start_time);
		QTreeWidgetItem* childItem = new QTreeWidgetItem(hearditem,
			QStringList() << QString::fromWCharArray(record_id->task_name) + " - " +
			dt.toString("yy/MM/dd hh:mm:ss"), ITEM_CHILD);
		childItem->setIcon(0, QIcon(":/res/image/record.png"));
		//ui.treeWidget_rec->setItemWidget(childItem,1,createItemWidget(ui.treeWidget_rec));
		QVariant data = QVariant::fromValue(record_id);
		childItem->setData(0, Qt::UserRole, data);


		ccd_record = ccd_record->next;
	}

	EagleData_FreeRecordMemory(eagle_record);
}

void CSimuPlayInfoWgt::EnableSelect(bool bEnable, int TotalFrame, int column, int line, int color_depth, int task_index, int record_index)
{
	setEnabled(bEnable);

	_column = column;
	_line = line;
	_color_depth = color_depth;
	_task_index = task_index;
	_record_index = record_index;

	ui.lineEdit_row->setText(QString::number(line));
	ui.lineEdit_colum->setText(QString::number(column));
	ui.lineEdit_depth->setText(QString::number(color_depth));

	if (TotalFrame > 0)
	{
		QIntValidator val;
		long frame_index_max = TotalFrame - 1;

		//start
		val.setRange(0, frame_index_max);
		ui.lineEdit_start->setText("0");
		ui.lineEdit_end->setText(QString::number(frame_index_max));
	}
	else
	{
 		ui.lineEdit_start->setText("0");
		ui.lineEdit_end->setText("0");
	}
}

bool CSimuPlayInfoWgt::toStartSimuPlay()
{
	MessageCmd*ptCmd = PrepareStartExp();
	if (!ptCmd)
	{
		return false;
	}

	_parent->getPlayWndBy(_devID, 1)->PostEvent(ptCmd);
	ui.btn_start->setEnabled(false);
	ui.btn_stop->setEnabled(true);
	_parent->setCtrlButtonStatus(true);

	return true;
}

void CSimuPlayInfoWgt::on_StartSimuPlay()
{
	toStartSimuPlay();
}

void CSimuPlayInfoWgt::on_StopSimuPlay()
{
	if (_parent->getPlayWndBy(_devID, 1)->IsExpOrCheck())
	{
		wxMessageBox(tr("当前正在读取仿真数据 请稍候结束!!\n设备:%1").arg(_PanelNam), this->windowTitle(), qobject_cast<QWidget*>(parent()));
		return;
	}

	if (ui.btn_stop->isEnabled())
	{
		_parent->getPlayWndBy(_devID, 1)->PostEvent(new MessageCmd(GT_CMD_REPLAY_STOP));
		ui.btn_start->setEnabled(true);
		ui.btn_stop->setEnabled(false);
		_parent->checkIsAllStop();
	}
}

void CSimuPlayInfoWgt::GetConfig(long &start_frame, long &stop_frame, long &interval, unsigned short &frame_rate, unsigned char& frame_taps, unsigned char& clock_hz, unsigned short& column, unsigned short& line, unsigned short& color_depth)
{
	start_frame = ui.lineEdit_start->text().toLong();
	stop_frame = ui.lineEdit_end->text().toLong();
	interval = 1;
	frame_rate = ui.lineEdit_hz->text().toLong();
	frame_taps = ui.cmb_taps->currentText().toLong();
	clock_hz = ui.cmb_hz->currentIndex();
	column = _column;
	line = _line;
	color_depth = _color_depth;
}

